How to script Microsoft Active Directory SIDs (Security Identifiers)

Published on
12,746 Points
1 Endorsement
Last Modified:
Community Pick
In this article we want to have a look at the directory attributes which are used by Microsoft to store the so called Security Identifiers (SID). These SIDs plays an important role in delegating and granting permissions and in authentication of trustee holders against the system. Important Active Directory attributes are stored as SIDs: objectSid, sIDHistory, tokenGroups. There also the wellknown SIDs which represents entries in permission configurations liek this: SYSTEM, ANONYMOUS, EVERYONE and so on...

How can we handle these SIDs in a VBScript? Basically, SID attributes can be read with LDAP/ADSI as Octet Strings. And: They are binary data with a rather complex structure.

This structure is explained in the Microsoft Technet documentation:

or even better in the SelfADSI tutorial:

The internal structure of a SID is based mainly on a so called Identifier Authority data block and several Sub-Authority data blocks. The SID starts with a leading Revision byte, followed by a byte which indicates the count of the Sub-Authority blocks. Then there is the Identifier Authority with six bytes (normal byte order), and after that the Sub-Authority blocks (4 bytes each wit a reverse byte order (Big Endian). So this is the SID:

1 byte Revision (always 1)
1 byte Sub-ID block count (for normal AD object SIDs always 5, for wellknown SIDs 1)
6 bytes ID Authoritiy block
n*4 bytes Sub Authority blocks

Now we a VBScript function to convert the binay LDAP attribute data of a SID attribute into a SID string (like "S-1-5-21-3478900112-2890103247-1138570132-6715"). This readable notation of a SID is called SDDL (Security Descriptor Definition Language). For this, we have to convert the binary data in an hex string first (a string of hexadecimal characters, two characters for each byte), after that we decode this hex string to a readable SID string.

So this is the function to convert a SID attribute into an SSDL string:
'you have to use other names and credentials from you own environment here!
Set obj = GetObject("LDAP://cn=user_xyz,cn=Users,dc=example,dc=com")

pureSidData = OctetToHexStr(obj.objectSid)
sDDLSidStr = HexStrToSID(pureSidData)

WScript.Echo obj.cn
WScript.Echo pureSidData
WScript.Echo sDDLSidStr

Function HexStrToSID(strSid) 
    'converts a raw SID hex string to the according SID string (SDDL)
    Dim i, data, offset
    ReDim data(Len(strSid)/2 - 1) 
    For i = 0 To UBound(data) 
        data(i) = CInt("&H" & Mid(strSid, 2*i + 1, 2)) 
    HexStrToSID = "S-" & data(0) & "-" & Byte6ToLong(data(2), data(3), data(4), data(5), data(6), data(7))

    blockCount = data(1)
    For i = 0 To blockCount - 1
        offset = 8 + 4*i
        HexStrToSID = HexStrToSID & "-" & Byte4ToLong(data(offset+3), data(offset+2), data(offset+1), data(offset))
End Function 

'___________________________________ helper functions 

Function OctetToHexStr(var_octet)
'converts pure binary data to a string with the according hexadecimal values
    OctetToHexStr = ""
    For n = 1 To lenb(var_octet)
        OctetToHexStr = OctetToHexStr & Right("0" & hex(ascb(midb(var_octet, n, 1))), 2)
End Function

Function Byte4ToLong(ByVal b1, ByVal b2, ByVal b3, ByVal b4)
'converts 4 bytes to the according lang integer value
    Byte4ToLong = b1
    Byte4ToLong = Byte4ToLong * 256 + b2
    Byte4ToLong = Byte4ToLong * 256 + b3
    Byte4ToLong = Byte4ToLong * 256 + b4
End Function

Function Byte6ToLong(ByVal b1, ByVal b2, ByVal b3, ByVal b4, ByVal b5, ByVal b6)
'converts 6 bytes to the according lang integer value
    Byte6ToLong = b1
    Byte6ToLong = Byte6ToLong * 256 + b2
    Byte6ToLong = Byte6ToLong * 256 + b3
    Byte6ToLong = Byte6ToLong * 256 + b4
    Byte6ToLong = Byte6ToLong * 256 + b5
    Byte6ToLong = Byte6ToLong * 256 + b6
End Function

Open in new window


Featured Post

Learn Ruby Fundamentals

This course will introduce you to Ruby, as well as teach you about classes, methods, variables, data structures, loops, enumerable methods, and finishing touches.

Join & Write a Comment

A query can call a function, and a function can call Excel, even though we are in Access. This is Part 2, and steps you through the VBA that "wraps" Excel functionality so we can use its worksheet functions in Access. The declaration statement de…
Please check the video also in regards to recovery of deleted emails from office 365 admin center and through the MFCMAPI tool. I have mentioned each and every step with the proper steps that need to be taken care of.

Keep in touch with Experts Exchange

Tech news and trends delivered to your inbox every month