When you are tasked with administering windows machines/servers more often than not you need to have Remote Server access tools for the version of Operating system you are supporting. What do you do when you can’t get those tools installed for administrative or other reasons. The best thing to do is to look for a means to do this in PowerShell. This article describes how to find user and group information via the Dll’s that are available on windows.
All users/groups and objects in active directory have unique Security Identifier’s. To be able to locate and translate SID’s the class System.DirectoryServices.AccountManagement. The current logged in user’s sid can be retrieved using:
Add-Type -AssemblyName System.DirectoryServices.AccountManagement [System.Security.Principal.WindowsIdentity]::getcurrent() AuthenticationType : CloudAP ImpersonationLevel : None IsAuthenticated : True IsGuest : False IsSystem : False IsAnonymous : False Name : somemachine\xxxxx Owner : S-1-5-24-2812812812-3456789123-4444444444-1001 User : S-1-5-24-2812812812-3456789123-4444444444-1001 Groups : {S-1-1-0, S-1-5-21-2242821411-3846915716-4272663257-1009, S-1-5-21-2242821411-3846915716-4272663257-1003, S-1-5-99-812...} AccessToken : Microsoft.Win32.SafeHandles.SafeAccessTokenHandle Token : 3688 UserClaims : {http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name: somemachine\xxxxx, http://schemas.microsoft.com/ws/2008/06/identity/claims/primarysid: S-1-5-24-2812812812-3456789123-4444444444-1001, http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid: S-1-1-0, http://schemas.xmlsoap.org/ws/2005/05/identity/claims/denyonlysid: S-1-5-189...} DeviceClaims : {} Claims : {http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name: somemachine\xxxxx, http://schemas.microsoft.com/ws/2008/06/identity/claims/primarysid: S-1-5-24-2812812812-3456789123-4444444444-1001, http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid: S-1-1-0, http://schemas.xmlsoap.org/ws/2005/05/identity/claims/denyonlysid: S-1-5-189...} Actor : BootstrapContext : Label : NameClaimType : http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name RoleClaimType : http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid
While the sid information has been redacted it is intact in terms of what would be displayed when calling the function. it’s groups we are looking for turns out this function has a Groups method.
[System.Security.Principal.WindowsIdentity]::getcurrent().groups BinaryLength AccountDomainSid Value ------------ ---------------- ----- 12 S-1-1-0 28 redactedAcountSid RedactedValue
The return value I received was much larger for this on a Corporate network especially if the (current) user is in a number of Groups.
Now that we have the Group SID’s now on to the process of Converting the SID’s into a human readable form. For the accounts discovered previously if we choose the first item [0] we can then see there is a .Translate on this item
([System.Security.Principal.WindowsIdentity]::getcurrent().groups[0]).translate OverloadDefinitions ------------------- System.Security.Principal.IdentityReference Translate(type targetType)
In order to do the translation we’ll need to specify the type that the dotnet class expects. It expects a type of system.security.principal.ntaccount . This is the only class from the documentation that has the type expected.
([System.Security.Principal.WindowsIdentity]::getcurrent().groups[0]).translate([system.security.principal.ntaccount]) Value ----- Everyone
The groups are known now to put this all together in a Foreach Loop to find out all the groups that the currently logged in user is a member of:
([System.Security.Principal.WindowsIdentity]::getcurrent().groups) | Foreach{( ` [System.Security.Principal.SecurityIdentifier]$_.value).Translate([system.security.principal.ntaccount])} Value ----- Everyone .....(more groups Redacted)
With a few more updates this script can be modified to find per user when in a domain scenario. Or for local users:
Add-Type -AssemblyName System.DirectoryServices.AccountManagement $userprincipal = ([System.DirectoryServices.AccountManagement.UserPrincipal]) -as [type] $up = $userprincipal::FindByIdentity([System.DirectoryServices.AccountManagement.ContextType]::Machine,[System.DirectoryServices.AccountManagement.IdentityType]::SamAccountName,"somemachine\defaultAccount") $up GivenName : MiddleName : Surname : EmailAddress : VoiceTelephoneNumber : EmployeeId : AdvancedSearchFilter : System.DirectoryServices.AccountManagement.AdvancedFilters Enabled : False AccountLockoutTime : ....... ....... ContextType : Machine Description : A user account managed by the system. DisplayName : SamAccountName : DefaultAccount UserPrincipalName : Sid : S-1-5-xx-xxxxxxxx-xxxxxxxxxxx-xxxxxxxxxxxxxxxx-503 Guid : .... Name : DefaultAccount $up.GetGroups() IsSecurityGroup : True GroupScope : Local Members : {DefaultAccount} Context : System.DirectoryServices.AccountManagement.PrincipalContext ContextType : Machine Description : Members of this group are managed by the system. DisplayName : SamAccountName : System Managed Accounts Group UserPrincipalName : Sid : S-1-5-xx-xxx Guid : DistinguishedName : StructuralObjectClass : Name : System Managed Accounts Group $up.getGroups().samacccountname System Managed Accounts Group
Now if you need who’s in a group either Locally with: [System.DirectoryServices.AccountManagement.ContextType]::Machine
Domain with
ApplicationDirectory with
[ system.DirectoryServices.Accountmanagement.contextType ]::ApplicationDirectory
I hope this helps someone out.
Until then
Keep Scripting
Thom