Joachim Otahal
Joachim Otahal

Reputation: 332

Powershell ADSI: Can I query the local Administrators group using a SID?

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

Answers (3)

Joachim Otahal
Joachim Otahal

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

Joachim Otahal
Joachim Otahal

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

enter image description here

Upvotes: 1

Doug Maurer
Doug Maurer

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

Related Questions