dcsimg

Managing Desktop Administration without Active Directory

By ServerWatch Staff (Send Email)
Posted Oct 28, 2001


by Marcin Policht

Delegation of Active Directory administration in Windows 2000 can be handled efficiently by granting different levels of permissions set on Active Directory objects. Similarly, by using restricted groups functionality, you can ensure that privileged groups on your servers and workstations will contain only specific accounts. You can also set the names for the built-in accounts Administrator and Guest. Marcin Policht's latest article presents a script that helps you handle the delegation of Active Directory administration in legacy domains. The script makes possible functionality like the ability to rename the local Administrator account, reset the password for the Admin account to an arbitrary value, and list the membership of a specified local group.

This functionality, however, is not available in legacy domains (although some functions, such as restricted groups have been introduced in the Windows NT 4.0 Option Pack). This also applies to Windows 2000 domains where workstations are still running Windows NT 4.0, since they can not process group policies.

The following script, provides these missing features. It allows you to accomplish the following: 

  • rename the local Administrator account, 
  • reset the password for this account to an arbitrary value, 
  • list the membership of a specified local group (typically used for local Administrators or Power Users), 
  • add any number of global groups into the specified local group (again, this is intended for local Administrators or Power Users, although it can be used with any other local group)

The script runs against any number of computers whose names are listed (one name per line) in a separate text file called PCList.txt (although the file name can be easily changed by modifying value of the strPCFile variable). Since a local Administrator account might have been previously renamed, the script does not rely on account names to locate it. Instead, its logic is based on the fact that the SID for Administrator's account is always in the form:

 S-1-5-[COMPUTERSID]-500. 
The last 3 decimal digits translate into 000001F4(hex), which in the little endian notation becomes F4010000. The SID is extracted by using functions available in ADsSecurity.dll. Prior to running the script, you will have to copy it into the %SystemRoot%\system32 folder (ADsSecurity.dll is part of the ADSI 2.5 SDK) and register using regsvr32.exe. This is done by running the following from the Command Prompt:
 regsvr32 ADsSecurity.dll 
You should receive the confirmation of successfull registration in the form of a message box. The script logs all of the activities in the file SetLocalAdmins.LOG (again, the file can easily be changed by modifying the value of the strLogFile variable). Here is the content of a sample log file:

Started logging at 10/21/2001 10:30:00 PM

**************** Started processing PC-TEST0001 ******************

*** Enumerating accounts in Administrators group ***

Member of Administrators group: BuiltInAdmin
SID of the account (if it ends with F4010000 then it's local Administrator):
010500000000000515000000828BA7287973DD0607E53B2BF4010000
*** Administrator Account Found ***
*** Administrator password reset ***
*** Administrator account renamed ***
Member of Administrators group: Domain Admins

*** Adding global groups to Administrators group ***

*** Adding AccountDomain1\Desktop Admins to Administrators group ***
*** Adding AccountDomain2\Desktop Admins to Administrators group ***
*** Adding AccountDomain1\Domain Admins to Administrators group ***
*** The group AccountDomain1\Domain Admins is already a member of Admin group ***

********* Finished processing PC-TEST0001 ***********

**************** Finished processing ****************

And below is the content of the script.

<Job id="LocalAdmins">
<Object id="objFSO" progid="Scripting.FileSystemObject" reference="yes"/>
<Object id="objShell" progid="WScript.Shell" reference="yes"/>
<Script language="VBScript">
Option Explicit
On Error Resume Next

Const ADS_SID_WINNT_PATH = 5
Const ADS_SID_HEXSTRING = 1

'***************************************************************************************************************
'*** SID for the Administrator's account is equal to S-1-5--500
'*** 500(decimal) translates into 000001F4(hex), which in the little endian notation becomes F4010000
'*** This value is stored in the HEX_500_LE constant
Const HEX_500_LE = "F4010000"

Const NO_OVERWRITE = TRUE		'used by CreateTextFile of the FileSystemObject

Dim strLocalAdminGroup 			'name of the local group, whose membership is to be modified
Dim objLocalAdminGroup			'object referencing local group, whose membership is to be modified
Dim strNewAdminName			'new name to be assigned to local Administrator account
Dim strPassword				'new password to be set for local Administrator account
Dim strLogFile				'name of the file containing script logging information
Dim strPCFile				'name of the file containing listing of target computers
Dim objLogFile				'object referencing log file
Dim objPCFile				'object referencing file containing listing of target computers
Dim arrGlobalAdminGroups		'array of global groups to be added to the local group separated by semicolons
Dim arrGlobalAdminGroup			'helper array containing domain and group name information
Dim objUserEnv				'object used to access set of User environment variables
Dim strTempFolder			'name of the temporary folder (where the log file is stored)
Dim strComputer				'name of a target computer
Dim objComputer				'object referencing a target computer
Dim blnAdminFound			'used to determine if the administrator's account has been found
Dim objLocalAdmin			'object referencing a member of local group whose membership is to be modified
Dim objSID				'object referencing SID of the objLocalAdmin account
Dim strSIDHex				'hex representation of the SID of the objLocalAdmin account
Dim intCount				'loop counter

strLocalAdminGroup = "Administrators"
strNewAdminName = "SomeoneElse"
strPassword = "Pa$$w0rd"
strLogFile = "SetLocalAdmins.LOG"
arrGlobalAdminGroups = _
   Split("AccountDomain1\Desktop Admins;AccountDomain2\Desktop Admins;AccountDomain1\Domain Admins",";")

'***************************************************************************************************************
'*** create log file in the TEMP folder

Set objUserEnv = objShell.Environment("USER")
strTempFolder = objShell.ExpandEnvironmentStrings(objUserEnv("TEMP"))
Set objLogFile = objFSO.CreateTextFile(strTempFolder & "\" & strLogFile, NO_OVERWRITE)

If Err.Number <> 0 Then
	WScript.Echo "Failed to create the log file. Terminating ..."
	WScript.Quit
End If

objLogFile.WriteLine("Started logging at " & Now())
objLogFile.WriteLine()

'***************************************************************************************************************
'*** open file containing list of PC names

strPCFile = "PCList.txt"
Set objPCFile = objFSO.OpenTextFile(strPCFile, ForReading)

If Err.Number <> 0 Then
	WScript.Echo "Failed to access the PC listing file. Terminating ..."
	WScript.Quit
End If

'***************************************************************************************************************
'*** for each PC listed in the file :
'*** rename local admin account,
'*** change password,
'*** add global groups to the local group

Do While NOT objPCFile.AtEndOfStream

    strComputer = objPCFile.ReadLine
    blnAdminFound = FALSE			'indicates whether local Administrator account has been found

    WScript.Echo "***************** Started processing " & strComputer & " ******************"
    objLogFile.WriteLine("**************** Started processing " & strComputer & " ******************")
    objLogFile.WriteLine()

    '***************************************************************************************************************
    '*** Enumerate local admin accounts

    Set objLocalAdminGroup = GetObject("WinNT://" & strComputer & "/" & strLocalAdminGroup)

    objLogFile.WriteLine("*** Enumerating accounts in " & strLocalAdminGroup & " group ***")
    objLogFile.WriteLine()

    For Each objLocalAdmin In objLocalAdminGroup.Members

	objLogFile.WriteLine("Member of " & strLocalAdminGroup & " group: " & objLocalAdmin.Name)

	'***************************************************************************************************************
	'*** Get SID Information, based on it find local Administrator account
	'*** SID for the Admistrator's account is equal to S-1-5--500

	If (NOT blnAdminFound) Then

	    Set objSID = CreateObject("ADsSID")
	    objSID.SetAs ADS_SID_WINNT_PATH, "WinNT://" & strComputer & "/" & objLocalAdmin.Name & ",user"
	    strSIDHex = objSID.GetAs(ADS_SID_HEXSTRING)

	    objLogFile.WriteLine("SID of the account (if it's ending with F4010000 then it's local Administrator): " & vbCrLF & strSIDHex)

	    If (strComp(Right(strSIDHex, 8), HEX_500_LE, vbTextCompare) = 0) Then

		objLogFile.WriteLine("*** Administrator Account Found ***")

		'***************************************************************************************************************
		'*** Reset the password for the local Administrator account

		objLocalAdmin.SetPassword(strPassword)

		If Err.Number = 0 Then
			objLogFile.WriteLine("*** Administrator password reset ***")
		Else
			objLogFile.WriteLine("*** Problems resetting Administrator password ***")
			objLogFile.WriteLine("*** Error :" & Err.Number & " " & Err.Description & " ***")
		End If
		'***************************************************************************************************************
		'*** Rename the username to Administrator

		Set objComputer = GetObject("WinNT://" & strComputer)
		objComputer.MoveHere objLocalAdmin.AdsPath, strNewAdminName

		If Err.Number = 0 Then
			objLogFile.WriteLine("*** Administrator account renamed ***")
		Else
			objLogFile.WriteLine("*** Problems renaming Administrator account ***")
			objLogFile.WriteLine("*** Error :" & Err.Number & " " & Err.Description & " ***")
		End If

		blnAdminFound = TRUE

	    End If

	End If

    Next

    '***************************************************************************************************************
    '*** Add global groups to local Administrators

    objLogFile.WriteLine()
    objLogFile.WriteLine("*** Adding global groups to " & strLocalAdminGroup & " group ***")
    objLogFile.WriteLine()

    For intCount = 0 To UBound(arrGlobalAdminGroups)

	objLogFile.WriteLine("*** Adding " & arrGlobalAdminGroups(intCount) & " to " & strLocalAdminGroup & " group ***")

	arrGlobalAdminGroup = split(arrGlobalAdminGroups(intcount), "\")

	objLocalAdminGroup.Add("WinNT://" & arrGlobalAdminGroup(0) & "/" & arrGlobalAdminGroup(1))

	If Err.Number = 0 Then
		objLogFile.WriteLine("*** " & arrGlobalAdminGroups(intCount) & " added successfully to " & strLocalAdminGroup & " group ***")
	Else
		Set objGroup = GetObject("WinNT://" & arrGlobalAdminGroup(0) & "/" & arrGlobalAdminGroup(1))
		If objGroup.IsMember(objLocalAdminGroup.aDSPath) Then
			objLogFile.WriteLine("*** The group " & arrGlobalAdminGroups(intCount) & " is already a member of " & strLocalAdminGroup & " group ***")
		Else
			objLogFile.WriteLine("*** Problems adding " & arrGlobalAdminGroups(intCount) & " to " & strLocalAdminGroup & " group ***")
			objLogFile.WriteLine("*** Error :" & Err.Number & " " & Err.Description & " ***")
		End If
	End If

    Next

    WScript.Echo "**************** Finished processing " & strComputer & " ******************"
    objLogFile.WriteLine()
    objLogFile.WriteLine("********* Finished processing " & strComputer & " ***********")
    objLogFile.WriteLine()

Loop

objLogFile.WriteLine("**************** Finished processing ****************")

objLogFile.Close
objPCFile.Close

</Script>
</Job>
Save it as SetLocalAdmins.wsf and execute it by running:

cscript //nologo SetLocalAdmins.wsf

Page 1 of 1


Comment and Contribute

Your name/nickname

Your email

(Maximum characters: 1200). You have characters left.