Tuesday, February 15, 2011

VBScript: Extract members of local Administrators group from SYDI-Server output

Sydi-Server is a great VBS tool that can extract local group memberships into an XML output. Unfortunately this is not always the greatest format to work with.

This VBScript can be pointed to a directory containing the SYDI-Server XML files and it will extract all members of the local Administrators groups into a CSV format.

Here is the script:


Dim xmlDoc, objNodeList, plot, nodeBook
Set objRegEx = CreateObject("VBScript.RegExp")



' =======================================================
' Set up files to be written and read
' =======================================================

Const ForReading = 1
Const ForWriting = 2
Const ForAppending = 8

Dim fso, logFile, dataFile, x, y

Set fso = CreateObject("Scripting.FileSystemObject")
Set dataFile = fso.CreateTextFile("Windows_Groups.txt", True) 'Output information from commands
Set logFile = fso.CreateTextFile("SessionLog.txt", True) 'Verbose Logging

If Err.Number <> 0 Then
wscript.echo "CRASH: Cannot open file for reading: Servers.txt. " & Err.Number & " " & Err.Description
wscript.quit
End If

' =======================================================
' Browse for folder containing XML files
' =======================================================


Const WINDOW_HANDLE = 0
Const BIF_EDITBOX = &H10
Const BIF_NONEWFOLDER = &H0200
Const BIF_RETURNONLYFSDIRS = &H1

Set objShell = CreateObject("Shell.Application")
Set wshShell = CreateObject("WScript.Shell")

'**Browse For Folder To Be Processed
strPrompt = "Please select the folder to process."
intOptions = BIF_RETURNONLYFSDIRS + BIF_NONEWFOLDER + BIF_EDITBOX
strTargetPath = "C:\"
strFolderPath = Browse4Folder(strPrompt, intOptions, strTargetPath)

Set objFolder = fso.GetFolder(strFolderPath)
Set objColFiles = objFolder.Files

For Each file In objColFiles
' Check if we are looking at an XML file
If UCASE(RIGHT(file.Name,3)) <> "XML" Then
logFile.WriteLine("WRN: Filename " & file.Name & " does not appear to be an XML file.")
Else
'perform the work

' =======================================================
' Browse each XML file for groups and memberships
' =======================================================

serverXMLSource=file.Name
fullServerXMLSource=objFolder&"\"&serverXMLSource
' msgbox fullServerXMLSource
serverName=LEFT(serverXMLSource,INSTR(serverXMLSource,".")-1)

logFile.WriteLine("INFO: Now processing server: " & serverXMLSource)

Set xmlDoc = CreateObject("Msxml2.DOMDocument")
xmlDoc.async=false
'xmlDoc.validateOnParse = false
xmlDoc.load(fullServerXMLSource)

if (xmlDoc.parseError.errorCode <> 0) Then
Dim myErr
Set myErr = xmlDoc.parseError
logFile.WriteLine("ERR: " & myErr.reason & ", " & myErr.srcText & ", " & myErr.line & ".")
'Msgbox ("Error: " & myErr.reason)
'Msgbox ("Error text: " & myErr.srcText)
'Msgbox ("Error line: " & myErr.line)
Else

' msgbox xmlDoc.xml
' Set elemList = xmlDoc.DocumentElement
' Set nodeList = elemList.SelectNodes("localgroups")
' for each item in nodeList
' msgbox "This is: " & item.xml
' Next

Set objChildNodes = xmlDoc.documentElement.childNodes
i = 0
childNodeNumber=0
For EAch strNode in objChildnodes
If strNode.NodeName = "localgroups" Then
childNodeNumber = i
'msgbox "Node : " & strNode.xml
End if
i=i+1
Next

If childNodeNumber = 0 Then
logFile.WriteLine("WRN: " & serverName & ": Unable to find a 'localgroups' element in " & serverXMLSource & ".")
End If
Set objLowerChildNodes = xmlDoc.DocumentElement.childNodes.item(childNodeNumber).ChildNodes
j = 0

For each strNode in objLowerChildNodes
If strNode.NodeName = "group" Then
groupName = objLowerChildNodes.item(j).GetAttribute("name")
if isNull(groupname) Then
'No point looking for members as we cannot even find a name of a group
logFile.WriteLine("WRN: " & serverName &_
": Unable to find a name tag for the returned group")
Else
'We can look for the next childnodes to find the members
'We will echo the group name to the output so that it appears even if empty.
if GroupName <> "Administrators" Then
dataFile.WriteLine(serverName & ",," & GroupName & ",No")
End If
Set objEvenLowerChildNodes = xmlDoc.DocumentElement.childNodes.item(childNodeNumber).ChildNodes.item(j).ChildNodes
k = 0
For each strLowerNode in objEvenLowerChildNodes
If strLowerNode.Nodename = "member" Then
memberName = objEvenLowerChildNodes.item(k).GetAttribute("name")
if isNull(memberName) Then
'Unable to find the name of a member
logFile.WriteLine("WRN: " & serverName &_
": Unable to find a name tag for the returned group member")
else
'We have the name of the group member
' ===========================================
' This is where we do our data manipulation
' And write it out to a file in the format:
' servername, membername, groupname, hpa, accountcode
' ============================================


' If HPA then test for Account Code
If GroupName = "Administrators" Then
hpa = "Yes"

' Allow to search for 9 consecutive digits
objRegEx.Global = false
objRegEx.Pattern = "\d{9}"
Set checkMatches = objRegEx.Execute(memberName)

'if checkMatches.Count> 0 Then
' For Each banana in checkMatches
' wscript.echo checkMatches.Count & " " & banana.Value
' Next
'End if

' - Test for JPicard or GISAdmin or 'break fix' accounts(5)
if INSTR(UCASE(memberName),"JPICARD") > 0 Then
accountCode = "5"
Elseif INSTR(UCASE(memberName),"GISADMIN") > 0 Then
accountCode = "5"
' Test for shared accounts (2)
Elseif INSTR(UCASE(memberName),"ADMIN") > 0 Then
accountCode = "2"
Elseif INSTR(UCASE(memberName),"\SSO") > 0 Then
accountCode = "2"
Elseif INSTR(UCASE(memberName),"\REDPLANET") > 0 Then
accountCode = "2"
' Test for adm accounts (?)
Elseif INSTR(UCASE(memberName),"\ADM-") > 0 Then
accountCode = "1"
' Test for \[1...9][0...9] (1)
Elseif checkMatches.Count > 0 Then
accountCode = "1"
' Test for \CEF_ \CMF_ _G_ Domain Admins and other groups (G)
Elseif INSTR(UCASE(memberName),"\CEF") > 0 Then
accountCode = "G"
Elseif INSTR(UCASE(memberName),"\CMF_") > 0 Then
accountCode = "G"
Elseif INSTR(UCASE(memberName),"_G_") > 0 Then
accountCode = "G"
Elseif INSTR(UCASE(memberName),"DOMAIN ADMINS") > 0 Then
accountCode = "G"
Elseif INSTR(UCASE(memberName),"\HP-OVE-GROUP") > 0 Then
accountCode = "G"
' Test for RRabling and personal SAM accounts (4)
Elseif INSTR(UCASE(memberName),"RRABLING") > 0 Then
accountCode = "1"
' Test for \IUSR ftpuser perfmon taskschedule and other service/app accounts(6)
Elseif INSTR(UCASE(memberName),"\IUSR") > 0 Then
accountCode = "6"
Elseif INSTR(UCASE(memberName),"FTPUSER") > 0 Then
accountCode = "6"
Elseif INSTR(UCASE(memberName),"PERFMON") > 0 Then
accountCode = "6"
Elseif INSTR(UCASE(memberName),"TASKSCHEDULE") > 0 Then
accountCode = "6"
Else
accountCode = "3"
End If

Else
hpa = "No"
End If

dataFile.WriteLine(serverName & "," & memberName & "," & GroupName & "," & hpa & "," & accountCode)

end if
else
' It was not an element named 'member' that was returned
logFile.WriteLine("WRN: " & serverName &_
": An element named 'member' should have been returned however the element" &_
"returned was: " & memberName)

end if

k = k + 1
Next
End If

Else
'It was not a element named 'group' that was returned
logFile.WriteLine("WRN: " & serverName &_
": An element named 'group' should have been returned hpwever the element" &_
"returned was: " & groupName)
End If


j = j + 1
Next






end if









End If
Next











' =======================================================
' Function for browsing for folders
' =======================================================


'**Browse4Folder Function
Function Browse4Folder(strPrompt, intOptions, strRoot)
Dim objFolder, objFolderItem

On Error Resume Next

Set objFolder = objShell.BrowseForFolder(0, strPrompt, intOptions, strRoot)
If (objFolder Is Nothing) Then
Wscript.Quit
End If
Set objFolderItem = objFolder.Self
Browse4Folder = objFolderItem.Path
Set objFolderItem = Nothing
Set objFolder = Nothing
End Function

No comments:

Post a Comment