Marc Lognoul's IT Infrastructure Blog

Cloudy with a Chance of On-Prem

Windows: Retrieving SID in String Format

Windows Logo

Introduction

Having the SID in string format can be very useful when troubleshooting security-related issues or configuring permission on securable objects when not pretty interface is available.

SID’s are usually stored or exposed in Hex format, therefore more difficult to humanly read and exploit; having them in string format makes their use handier.

While there are, as usual, multiple ways to, this article describes the most common ones.

To readers less used with SID and windows security, by Security Principal it is meant Computer, User, Groups and so on…

Using WHOAMI

From a command-prompt, the Windows built-in too WHOAMI will display the SID of the interactively logged-on user using the parameter hereunder

whoami /user /sid

If you wish to display the complete group membership as well, add the /groups parameter:

whoami /user /groups  /sid

Note: This command is particularly useful since is actually dumps the user’s token applicable to the interactive session.

Using PsGetSid

Sysinternals’s PsGetSid tool, can translate virtually any SID, local, domain user, group, computer and so on and is a no-brainer to use. You can even run it against a remote computer with alternate credentials Example:

PsGetSid MYDOMAINMYUSER

Using PowerShell and .Net

System.Security.Principal Namespace is easy to use from PowerShell. Here is how to do using the Translate method of the NTAccount class:

$NtSecurityPrincipal = new-object System.Security.Principal.NTAccount(“MYDOMAIN”, “MYUSER”)

$NtSecurityPrincipal.Translate([System.Security.Principal.SecurityIdentifier])

Using WMI

While using WMI might be slower, it’s advantage over other methods resides in the fact that you can call it from almost any language, from old WSH to PowerShell, not to mention WMIC. Let’s start with WSH/VBS:

strComputer = “.”

Set objWMIService = GetObject(“winmgmts:\” & strComputer & “rootcimv2”)

Set objAccount = objWMIService.Get(“Win32_UserAccount.Name=’SP070807$’,Domain=’CORP'”)

Wscript.Echo objAccount.SID

And now with WMIC:

wmic USERACCOUNT WHERE (Domain=”MYDOMAIN” AND Name=”MYUSER”) Get Sid

Remember that the class Win32_UserAccount will work for both User and Computer accounts (add $ as suffix for the latter). For groups, use the class Win32_Group.

Using IADsNameTranslate

IADsNameTranslate is an older COM Interface, therefore useable from WSH as well as from PowerShell. While it is a little heavier to use (more code for the same result), it allows to translate from multiple name format and in multiple directions, which makes it still very flexible and useful. Here is an example in WSH/VBS provided by ADSI mogul Richard L. Mueller:

Option Explicit
Dim objUser, arrSid, strSidHex, objTrans, strUserDN, strSidDec

‘ Constants for the NameTranslate object.
Const ADS_NAME_INITTYPE_GC = 3
Const ADS_NAME_TYPE_1779 = 1
Const ADS_NAME_TYPE_SID_OR_SID_HISTORY_NAME = 12

‘ Bind to object.
Set objUser = GetObject(“LDAP://cn=Test,ou=Sales,dc=MyDomain,dc=com”)

‘ Retrieve SID and convert to hex string, then to decimal string.
arrSid = objUser.objectSid
strSidHex = OctetToHexStr(arrSid)
Wscript.Echo strSidHex
strSidDec = HexStrToDecStr(strSidHex)
Wscript.Echo strSidDec

‘ Use the NameTranslate object to convert objectSid to
‘ Distinguished Name.
Set objTrans = CreateObject(“NameTranslate”)
‘ Initialize NameTranslate by locating the Global Catalog.
objTrans.Init ADS_NAME_INITTYPE_GC, “”
‘ Use the Set method to specify the SID format of the object name.
objTrans.Set ADS_NAME_TYPE_SID_OR_SID_HISTORY_NAME, strSidDec
‘ Use the Get method to retrieve the Distinguished Name of the user object.
strUserDN = objTrans.Get(ADS_NAME_TYPE_1779)
Wscript.Echo strUserDN

Wscript.Quit

Function OctetToHexStr(arrbytOctet)
‘ Function to convert OctetString (byte array) to Hex string.

  Dim k
  OctetToHexStr = “”
  For k = 1 To Lenb(arrbytOctet)
    OctetToHexStr = OctetToHexStr _
      & Right(“0” & Hex(Ascb(Midb(arrbytOctet, k, 1))), 2)
  Next
End Function

Function HexStrToDecStr(strSid)
‘ Function to convert hex Sid to decimal (SDDL) Sid.
  Dim arrbytSid, lngTemp, j

  ReDim arrbytSid(Len(strSid)/2 – 1)
  For j = 0 To UBound(arrbytSid)
    arrbytSid(j) = CInt(“&H” & Mid(strSid, 2*j + 1, 2))
  Next

  HexStrToDecStr = “S-” & arrbytSid(0) & “-” _
    & arrbytSid(1) & “-” & arrbytSid(8)

  lngTemp = arrbytSid(15)
  lngTemp = lngTemp * 256 + arrbytSid(14)
  lngTemp = lngTemp * 256 + arrbytSid(13)
  lngTemp = lngTemp * 256 + arrbytSid(12)

  HexStrToDecStr = HexStrToDecStr & “-” & CStr(lngTemp)

  lngTemp = arrbytSid(19)
  lngTemp = lngTemp * 256 + arrbytSid(18)
  lngTemp = lngTemp * 256 + arrbytSid(17)
  lngTemp = lngTemp * 256 + arrbytSid(16)

  HexStrToDecStr = HexStrToDecStr & “-” & CStr(lngTemp)

  lngTemp = arrbytSid(23)
  lngTemp = lngTemp * 256 + arrbytSid(22)
  lngTemp = lngTemp * 256 + arrbytSid(21)
  lngTemp = lngTemp * 256 + arrbytSid(20)

  HexStrToDecStr = HexStrToDecStr & “-” & CStr(lngTemp)

  lngTemp = arrbytSid(25)
  lngTemp = lngTemp * 256 + arrbytSid(24)

  HexStrToDecStr = HexStrToDecStr & “-” & CStr(lngTemp)

End Function

Constraints and Limitations

In most case, it will only be possible to retrieve the principal’s primary SID which was assign by the system (local or AD) at object creation-time. The primary SID is opposed to the SID’s from the SidHistory attribute, which contains the primary SID’s of a principal before it was migrated to the new domain

Most of Name-To-SID translation requires authenticated RPC-based communication if the remote computer. Therefore, the necessary network connectivity must be in-place as well and the caller must be able to authenticate to the remote security authority (AD or local).

A Word over Security Configuration

There are many security setting affecting the Name-To-Sid (and vice-versa) translation. For a comprehensive troubleshooting approach, you can refer to the following blog post:

More Information

Advertisements