Community Pick: Many members of our community have endorsed this article.

How to script Microsoft Active Directory SIDs (Security Identifiers)

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 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


Comments (0)

Have a question about something in this article? You can receive help directly from the article author. Sign up for a free trial to get started.