Reputation: 332
I am in a multilanguage client environment. The local administrators are "Administratoren", "Administrators","Administradores","Administrateurs" and so on. This works to get the group members using Invoke-Expression:
PS C:\> Get-LocalGroupMember -SID "S-1-5-32-544"
ObjectClass Name PrincipalSource
----------- ---- ---------------
Benutzer PC-JOU\Administrator Local
Benutzer PC-JOU\Jou Local
Working example using the normal group name, for example on a German client WITHOUT needing Invoke-*:
PS C:\> $ADSI = [ADSI]"WinNT://IP-of-computer/Administratoren"
PS C:\> $ADSI.Invoke("Members") | foreach {$_.GetType().InvokeMember("ADsPath", 'GetProperty', $null, $_, $null)}
WinNT://PC-JOU/Administrator
WinNT://PC-JOU/Jou
But I cannot get this to work with a SID to have this international:
PS C:\> $ADSI = [ADSI]"WinNT://IP-of-computer/S-1-5-32-544"
PS C:\> $ADSI.Invoke("Members") | foreach {$_.GetType().InvokeMember("ADsPath", 'GetProperty', $null, $_, $null)}
Ausnahme beim Abrufen des Elements "Invoke": "Der Gruppenname konnte nicht gefunden werden."
In Zeile:1 Zeichen:1
+ $ADSI.Invoke("Members") | foreach {$_.GetType().InvokeMember("ADsPath ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], ExtendedTypeSystemException
+ FullyQualifiedErrorId : CatchFromBaseGetMember
I got so far to see the propertyvalue of the sid:
PS C:\> $ADSI.objectSid
1
2
0
0
0
0
0
5
32
0
0
0
32
2
0
0
PS C:\> $ADSI.objectSid.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True False PropertyValueCollection System.Collections.CollectionBase
Any idea how I can get this to work, using [ADSI] with the SID value of the local admin? It would save me using Invoke-Expression method.
Upvotes: 0
Views: 5195
Reputation: 332
I've been using this version since May 2023, but never had the time go post this improved version. Separate answer since it does not rely on WMI, it uses pure ADSI and works if the target system is from Windows 2000 up to Windows 11 / Server 2025. It works (tested) on German, English, French and Spanish target systems, which all have different names for the "Administrator" user and "Administrators" group. You don't have to use the full domain name, the shorter netbios name works too, but in many environments the full name is faster. The machine you query from should be at least Server 2008 R2/Windows 7 with Powershell 5.1, I never tested anything below.
$LocalIdentities = ([ADSI]"WinNT://Targetmachine.domain.local").Children.Where({$_.Path -like "WinNT://*/*/*"}) |
Select-Object @{Name="Name";Expression={$_.Name[0]}},
SchemaClassName,
objectSid,
@{Name="SID";Expression={[System.Security.Principal.SecurityIdentifier]::new($_.ObjectSid.value, 0).Value}}
$LocalAdmin = $LocalIdentities.Where({$_.SID -like "S-1-5-21-*-*-*-500"}).Name
$LocalAdminGroup = $LocalIdentities.Where({$_.SID -eq "S-1-5-32-544"}).Name
$LocalMachineSid = $LocalIdentities.Where({$_.SID -like "S-1-5-21-*-*-*-500"}).SID.Replace("-500","")
Which will give you, for example in an German target system, this:
PS C:\> "$LocalAdmin`n$LocalAdminGroup`n$LocalMachineSid"
Administrator
Administratoren
S-1-5-21-628914358-228923571-32354782202
Upvotes: 0
Reputation: 332
SOLVED: As per comment from Santiago Squarzon, I can get the actual local administrator group name with WMI. With the right group name everything else is solved.
Working example: I query from an English domain controller, getting the local "Administratoren" from the German remote machine:
$RemoteAdminGroupName = (Get-WmiObject Win32_Group -Computername 192.168.33.57 -Filter "SID='S-1-5-32-544'").Name
"local admin group on remote machine: $RemoteAdminGroupName"
$ADSI = [ADSI]"WinNT://192.168.33.57/$RemoteAdminGroupName"
$ADSI.Invoke("Members") | foreach {$_.GetType().InvokeMember("ADsPath", 'GetProperty', $null, $_, $null)}
Result:
local admin group on remote machine: Administratoren
WinNT://S2016-DE-TEST/Administrator
WinNT://PKI-TEST/Domain Admins
Upvotes: 1
Reputation: 8868
How about just looking up the group name via the SID first.
$AdminGroupSid = 'S-1-5-32-544'
$AdminGroup = New-Object System.Security.Principal.SecurityIdentifier($AdminGroupSid)
$AdminGroupName = $AdminGroup.Translate([System.Security.Principal.NTAccount]).Value -replace '.+\\'
Now just process your normal code
$ADSI = [ADSI]"WinNT://IP-of-computer/$AdminGroupName"
$ADSI.Invoke("Members") | ForEach-Object {
$_.GetType().InvokeMember("ADsPath", 'GetProperty', $null, $_, $null)
}
Upvotes: 1