Search code examples
vbscriptactive-directoryldap

Enumerate all users including SIDs


I have written a VBScript to list all the users and selected info from AD. But I would like to add SIDs to the list of user info without having to connect to each user object. Any ideas?

' Set up the connection to the domain
Set objConnection = CreateObject( "ADODB.Connection" )
Set objCommand = CreateObject("ADODB.Command")
objConnection.Provider = "ADsDSOObject"
objConnection.Open "Active Directory Provider"
Set objCommand.ActiveConnection = objConnection

' Configure the Active Directory connection
objCommand.Properties("Page Size") = 1000
objCommand.Properties("Searchscope") = ADS_SCOPE_SUBTREE

' Filter to search AD with
strFilter = "(&(objectCategory=person)(objectClass=user))"

' Attributes to return with the search
strAttrib = "sAMAccountName,cn,sn,givenName,title,department,company,physicalDeliveryOfficeName,mail,telephoneNumber,l,st,postalCode,co,whenCreated,whenChanged,manager,userAccountControl,objectSid"

' Build the AD query
strQuery = "<LDAP://dc=yourdomain,dc=com>;" & strFilter & ";" & strAttrib & ";subtree"

' Create the file system object
Set objFSO = CreateObject( "Scripting.FileSystemObject" )
Set objFile = objFSO.CreateTextFile( "users.csv" )
objFile.WriteLine """Domain"",""User ID"",""CN"",""Last Name"",""First Name"",""Email"",""SID"""

' Execute the query
objCommand.CommandText = strQuery
Set objRecordSet = objCommand.Execute

Do Until objRecordSet.EOF
    objFile.WriteLine objRecordSet.Fields( "objectSid" ).Value
Loop

Unfortunately this returns nothing.


Solution

  • For one thing, you have an infinite Do loop because it's missing a objRecordSet.MoveNext statement.

    With that said, the most likely reason for your issue is the data type of the objectSid attribute. SIDs in Active Directory aren't stored as strings, but in a binary format. If you check the result of TypeName(objRecordSet.Fields("objectSid").Value) you'll see that it's Byte(), so writing the raw values to a text file won't produce readable output. You need to convert SIDs from binary to string form with something like this in order to get a human-readable result:

    Function DecodeSID(binSID)
      ReDim o(LenB(binSID))
    
      ' Convert binary string to octet array.
      For i = 1 To LenB(binSID)
        o(i-1) = AscB(MidB(binSID, i, 1))
      Next
    
      ' Convert octet array to (human-readable) SID string.
      sid = "S-" & CStr(o(0)) & "-" & OctetArrayToString _
            (Array(o(2), o(3), o(4), o(5), o(6), o(7)))
      For i = 8 To (4 * o(1) + 4) Step 4
        sid = sid & "-" & OctetArrayToString(Array(o(i+3), o(i+2), o(i+1), o(i)))
      Next
    
      DecodeSID = sid
    End Function
    
    Function OctetArrayToString(arr)
      v = 0
      For i = 0 To UBound(arr)
        v = v * 256 + arr(i)
      Next
    
      OctetArrayToString = CStr(v)
    End Function