VBSCRIPT: Add New Domain's Admins to Local Administrators Programmatically

Filed under: Active Directory, Quick Code, VBScript — Written by Chrissy on Friday, July 28th, 2006 @ 3:44 am

In order for Active Directory Migration Tool (ADMT) to install its Agent on a newly migrated computer, the user running the ADMT tool must have local Administrator access. Otherwise, the error log shows something similar to the following:

WRN1:7290 Processor architecture for machine \NT4MACHINE is unknown, Error accessing registry key SYSTEM\CurrentControlSet\Control\Session Manager\Environment rc=5 Access is denied.
Failed to install agent on \NT4MACHINE, rc=5 Access is denied. Unable to access ADMIN$ share on the machine 'NT4MACHINE'. Make sure the share exists and the account running ADMT is a member of local administrators group on the machine 'NT4MACHINE'. hr=0x80070005. Access is denied.

Here is a basic script that will go through each of the Windows workstations on the old domain and add the new domain's "Domain Admins" group to the workstation's local Administrators group. If the machine is a Windows Server OS, it will be ignored. Change the newDomain and oldDomain variables to match your network.

Quick Code

newDomain = "NEW2K3"
oldDomain = "OLDNT4"
 
Set objADGroup = GetObject("WinNT://" & newDomain & "/Domain Admins,group")
Set objOldDomain = GetObject("WinNT://" & oldDomain)
  objOldDomain.Filter = Array("Computer")
    For Each Computer In objOldDomain
      strComputer = Computer.Name
       Set objWMIService = GetObject("winmgmts:" & strComputer & "\root\cimv2")
                  Set colSettings = objWMIService.ExecQuery ("SELECT * FROM Win32_OperatingSystem")
                    For Each objOperatingSystem in colSettings
                      If InStr(UCase(objOperatingSystem.Name),"SERVER") = 0 Then
         Set objLocalGroup = GetObject("WinNT://" & strComputer & "/Administrators,group")
        objLocalGroup.Add(objADGroup.AdsPath)
        Set objLocalGroup = Nothing
                      End If
                    Next
                  Set colSettings = Nothing
                  Set objWMIService = Nothing
    Next
Set objADGroup = Nothing

Also, if you do not have the workstation's primary DNS server set to the new domain's DNS servers, ADMT will quit with the following error: ERR3:7075 Failed to change domain affilation, hr=8007054b The specified domain either does not exist or could not be contacted.

Use this code to change DNS servers domain-wide

oldDomain = "OLDNT4"
DNSServerArray = "192.168.1.1,192.168.1.2"
 
Set objOldDomain = GetObject("WinNT://" & oldDomain)
  objOldDomain.Filter = Array("Computer")
    For Each Computer In objOldDomain
      strComputer = Computer.Name
       Set objWMIService = GetObject("winmgmts:" & strComputer & "\root\cimv2")
                  Set colSettings = objWMIService.ExecQuery ("SELECT * FROM Win32_OperatingSystem")
                    For Each objOperatingSystem in colSettings
                      If InStr(UCase(objOperatingSystem.Name),"SERVER") = 0 Then
         arrNewDNSServerSearchOrder = Array(DNSServerArray)
         Set colNicConfigs = objWMIService.ExecQuery("SELECT * FROM Win32_NetworkAdapterConfiguration WHERE IPEnabled = True")
         For Each objNicConfig In colNicConfigs
         intSetDNSServers = objNicConfig.SetDNSServerSearchOrder(arrNewDNSServerSearchOrder)
         If intSetDNSServers = 0 Then Wscript.Echo "Oops, problem on " & strComputer
         Next
                      End If
                    Next
                  Set colSettings = Nothing
                  Set objWMIService = Nothing
    Next

Also, that probably won't be effective on machines set to accept DNS servers via DHCP, though I haven't tested. Be sure you reboot after resetting the DNS, otherwise, you'll run into the following error: The ADSI property cannot be found in the property cache ErrCode=8000500d Go ahead and reboot the workstation, it should solve the problem.

VBScript: Sort Array

Filed under: Quick Code, VBScript — Written by Chrissy on Friday, July 28th, 2006 @ 2:56 am

Found this code and wanted to bookmark it... from VisualBasicScript.com's Forums

Function fSortArray(aSortThisArray)
Set oArrayList = CreateObject("System.Collections.ArrayList" )
For iElement = 0 To UBound(aSortThisArray)
  oArrayList.Add aSortThisArray(iElement)
Next
oArrayList.Sort
set fSortArray = oArrayList
Set oArrayList = Nothing
End Function

AD: Change Default Login Domain after Migration

Filed under: Active Directory, Tech Stuff — Written by Chrissy on Friday, July 28th, 2006 @ 2:20 am

When adding a trusted domain or migrating computers to a new domain, the login prompt often defaults to the old domain or the name of the workstation. This can cause confusion for users who are often confused about computers by default ;)
In order to make their lives easier, you can set their default login domain by modifying the computer's registry (reg add available only on XP and 2k3). In the examples below "NEWDOMAINNAME" is the new domain name and "wkstnName" is the recently migrated workstation name.

run from command line..

Running the command locally:
reg add "HKLM\Software\Microsoft\Windows NT\CurrentVersion\Winlogon" /v DefaultDomainName /f /t REG_SZ /d "NEWDOMAINNAME"
 
Remotely modifying the key:
reg add "\wkstnName\HKLM\Software\Microsoft\Windows NT\CurrentVersion\Winlogon" /v DefaultDomainName /f /t REG_SZ /d "NEWDOMAINNAME"

If you use Win2000, you can modify those values with regedit or download the Windows 2000 SP4 Support Tools which installs reg.exe.

Or you can do it in WSH..

const HKEY_LOCAL_MACHINE = &H80000002
strComputer = "wkstnName"
  Set objRReg = GetObject("winmgmts:{impersonationLevel=impersonate}!" & strComputer & "\root\default:StdRegProv")
    strKeyPath = "Software\Microsoft\Windows NT\CurrentVersion\Winlogon"
    strValueName = "DefaultDomainName"
    strValue = "NEWDOMAINNAME"
    objRReg.SetStringValue HKEY_LOCAL_MACHINE,strKeyPath,strValueName,strValue
  Set objRReg = Nothing

Microsoft also provides a way to do this via Group Policy. Oh, as an added bonus, this also works instantly for Terminal Services. On one of my machines, it would always default to blank or the wrong domain. I tested this script on it and now I get prompted with the most proper domain each time.

keywords: default domain login, trusted domain default login, dual domain login default

MACBOOK: Unexpected Shutdowns

Filed under: Tech Stuff — Written by Chrissy on Monday, July 24th, 2006 @ 7:54 pm

Dang, Gina! My black Macbook has been a pain this past week. I'm having unexpected shutdowns galore. Called Apple about 5 times and they offered to replace it as it is a DOA.

I've read around the Internet that others are experiencing this problem... Many have concluded that it is a faulty logic board. Here are a few of my observations

  • My Macbook moos (which drives me crazy)
  • This started happening last week; not long after I ran the Apple Update to get an updated that supposedly made Macbooks run "up to 10 degrees cooler". My Macbook gets hot, but so did my Sony Vaio. Excessive heat not a Macbook issue, as Dells run at about the same temperatures.
  • It happens in both OS X and Windows
  • It happens frequently after coming back from Stand By mode, but not exclusively.
  • Often times, the fans start spinning up high like the CPU is in overdrive but the CPU is running normally. Sometimes, the shutdown is totally unexpected with no prior fan revving.
  • Unexpected shutdowns have occured when my computer has been unplugged and plugged in to different power supplies (I've got one at work and one at home)
  • It's happened with the battery both in and out
  • Sometimes, it refuses to reboot unless I hold down the power button for 3 seconds or more. During this time, the laptop light flashes and there is a loud beep.
  • It's gotten very hot doing video conversions yet hasn't shut down. On Saturday, I did some CPU-intensive work with no problems. Three hours later when the laptop was cool, however, the laptop shut down.
  • I've reseated my ram and even switched the module positions.

I'm glad they're doing DOA though.. it will suck to reinstall everything but at least there's a possiblity I can get a Macbook that doesn't moo. *Crosses fingers* This computer has been a bit problematic but I'm still gad I got it.. It's extremely fast and looks great. I still dig it.

VBScript: Traverse Directories & Subdirectories Snippet

Filed under: Quick Code, VBScript — Written by Chrissy on Thursday, July 20th, 2006 @ 11:15 pm

This snippet has come in handy quite a few times for me...

Call ListFolderContents("C:\Windows\System32\Drivers")
 
Sub ListFolderContents(path)
     set fs = CreateObject("Scripting.FileSystemObject")
     set folder = fs.GetFolder(path)
         Msgbox folder.path
 
         For each item in folder.SubFolders
                  ListFolderContents(item.Path)
         Next
     set folder = Nothing
     set fs = Nothing
End Sub

ADMT: Auto-Expired Password Clean-Up

Filed under: Active Directory, Tech Stuff — Written by Chrissy on Friday, July 14th, 2006 @ 6:11 am

I'm using Microsoft's Active Directory Migration Tool to migrate users from an NT 4.0 Domain to a Win2k3 Domain. The process seems mostly flawless so far except that the password settings (not the password itself) are lost after migrating the users and their passwords. Suddenly, all migrated users on the new domain have expired passwords and are thus required to enter in a new password after their first successful login on the new domain. This new requirement does not comply with our old policy so I've written a VBS script to address the issue.

Below is a script that goes through each of the accounts on the new domain and, if the account is not disabled, sets the password to never expire and it also unchecks the box that declares "User Must Change Password at Next Login."

Set objDomain= GetObject("WinNT://newdomain")
  objDomain.Filter = Array("User")
    For Each User In objDomain
      If User.Accountdisabled = 0 then
        User.PasswordExpired = 0
        User.Put "UserFlags", Flags OR &H10000
        User.SetInfo
      End if
    Next
Set objDomain = Nothing

IIS: Instantly Ban IPs Attempting to Login to MS-FTP as Administrator

Filed under: IIS, Quick Code, Security, VBScript — Written by Chrissy on Sunday, July 2nd, 2006 @ 5:49 pm

UPDATE 12/18/06: The startup script has been modified slightly (cscript.exe was changed to wscript.exe). Now, console users will no longer encounter a blank black box upon login.
UPDATE 11/21/06: Now that banning at the IP level has been added to the script, offending users are completely banned before they can even attempt a second login on Windows 2003 machines. Windows 2000 machines still have a slight delay.
UPDATE 1/18/07: I updated the code so that it does not throw out an "unknown" error on line 48 for Win2k users. Thanks to the commenters for figuring that out. Also, check the comments for some really great script modification and ideas posted by blog visitors. Thanks to everyone who has posted!

Recently while reviewing my Windows Events, I noticed over 2800 failed login attempts to my Microsoft FTP server. Apparently, a bot was trying to brute force the Administrator password. Thankfully, I soon determined that there were only two IPs I needed to ban. The FTP server needs to be accessed by my employer's clients so I couldn't just change the port (as I did when I found 30,000+ SSH login attempts to my Linux box). Thus, I decided to instantly ban any IPs attempting to login as Administrator. I did this using a VBScript file (saved as: C:\Scripts\Startup\banftpips.vbs) that is set to execute upon boot-up. This can be done like so.

banftpips.vbs

'****************************************************************************
' This script created by Chrissy LeMaire (clemaire@gmail.com)
' Website: http://netnerds.net/
'
' NO WARRANTIES, etc.
'
' This script instantly bans IP addresses trying to login to FTP
' using the NT account "Administrator"
'
' Run this script on the FTP server. It sits in the back and waits for an
' event viewer "push" that lets it know someone failed FTP authentication.
'
' This script has only been tested on Windows Server 2003. It assumes, as it
' should, that there are no legitimate Administrator account FTP logins.
'
' "What it does"
' 1. Sets an Async Event Sink to notify the script when someone fails MS-FTP auth
' 2. When alerted, the script parses the last day's FTP logs for all FTP sites (this
'    is because the Event Viewer doesn't tell you which FTP site, if you have more than
'    one, is the one getting hit)
' 3. Compiles the list of IPs to be banned and then bans them using IIS /and/
'    IP level banning (thanks Spencer @ netortech.com for the idea)
'*****************************************************************************
 
' Push Event Viewer Alert
    Set objWMIService = GetObject("winmgmts:{(security)}!root/cimv2")
    Set eventSink = wscript.CreateObject("WbemScripting.SWbemSink", "EVSINK_")
    strWQL = "Select * from __InstanceCreationEvent where TargetInstance isa  'Win32_NTLogEvent' and TargetInstance.SourceName = 'MSFTPSVC' and TargetInstance.EventCode = 100"
    objWMIService.ExecNotificationQueryAsync eventSink,strWQL
 
' Keep it going forever
While (True)
    Wscript.Sleep(1000)
Wend
 
Sub EVSINK_OnObjectReady(objObject, objAsyncContext)
  If InStr(LCase(objObject.TargetInstance.Message),"administrator") > 0 Then
    Set objFTPSVC = GetObject("IIS://localhost/MSFTPSVC")
    Set WshShell = CreateObject("WScript.Shell")
    Set objFSO = CreateObject("Scripting.FileSystemObject")
    Set objLog = CreateObject("MSWC.IISLog")
    Set objDictionary = CreateObject("Scripting.Dictionary")
    Set objFTPIPSec = objFTPSVC.IPSecurity
    
    'Get IP address of server so we can use it later to give the offending IP a bad route
    Set IPConfigSet = GetObject("winmgmts:\\.\root\cimv2").ExecQuery("SELECT * FROM Win32_NetworkAdapterConfiguration WHERE IPEnabled=TRUE")
    for each IPConfig in IPConfigSet
      if Not IsNull(IPConfig.DefaultIPGateway) then serverIP =  IPConfig.IPAddress(0)
    Next
    Set IPConfigSet = Nothing
 
    'Iterate through each FTP site. See #2 up above.
      For Each objSITE in objFTPSVC
        If lcase(objSITE.class) = "iisftpserver" Then
          ftpLogFilePath =  WshShell.ExpandEnvironmentStrings(objSITE.LogFileDirectory) & "\msftpsvc" & objSITE.Name
      
          Set objFolder = objFSO.GetFolder(ftpLogFilePath)
            Set objFiles = objFolder.Files
              For Each fileName In objFiles
                lastFile = fileName
              Next
            strLogFile = lastFile
            Set file = Nothing
          Set objFolder = Nothing
          
          'Use the IIS log file parser provided by MSFT
          objLog.OpenLogFile strLogFile, 1, "MSFTPSVC", 1, 0
            '(FileName,IOMode,ServiceName,ServiceInstance,OutputLogFileFormat)
            ' 0 = NotApplicable, 1 = ForReading  
            While NOT objLog.AtEndOfLog
              objLog.ReadLogRecord
              If LCase(objLog.URIStem) = "administrator" Then
                ClientIP = objLog.ClientIP
                  If objDictionary.Exists(ClientIP) = False Then
                      'Kill the route to the machine then add it to the array of banned IPs.
                      Set WshShell = WScript.CreateObject("WScript.Shell")
                    WshShell.Run "ROUTE ADD " & clientIP & " MASK 255.255.255.255 " & serverIP, 1, True
                    Set WshShell = Nothing
                    objDictionary.Add ClientIP, "255.255.255.255" '255 is just there for padding.
                  End If
              End If
            Wend  
          objLog.CloseLogFiles 1
        End If
      Next
    
      'Append the newly banned IPs to the currently banned IPs  
      If objDictionary.Count > 0 And objFTPIPSec.GrantByDefault = True Then
        bannedIPArray = objFTPIPSec.IPDeny
          For i = 0 to ubound(bannedIPArray)
          clientIP = Left(bannedIPArray(i),InStr(bannedIPArray(i),",")-1)
            If objDictionary.Exists(ClientIP) = False Then
              objDictionary.Add bannedIPArray(i), "255.255.255.255"
            End If
          Next
          
        objFTPIPSec.IPDeny = objDictionary.Keys
        objFTPSVC.IPSecurity = objFTPIPSec
        objFTPSVC.SetInfo
      End If
      
    Set objFTPIPSec = Nothing
    Set objDictionary = Nothing
    Set objLog = Nothing
    Set objFSO = Nothing
    Set objFTPSVC = Nothing
  End If
  End Sub

Once the IP has been added to the ban list, the user will no longer be able to connect to the machine via TCP/IP as it has been given a bad route. If the server reboots, it will lose the route but the IP will still be banned in IIS. The offending user will then see the following message:

Connected to ftpserver
530 Connection refused, unknown IP address.
421 Service not available, closing control connection.
Connection closed by remote host.

Note that this bans the IPs on a global FTP level. You will find the banned IPs listed under Windows 2003 @ IIS -> FTP -> Properties and under Windows 2000 @ IIS -> Hostname -> Properties -> FTP Service -> Edit -> Directory Security. This means you will not find it on the properties of the Default FTP Site. This pro-actively bans the IPs from hitting other FTP sites in an IIS setup with multiple FTP sites. In addition, with the new ban at the IP level, the machine can't even contact your server until your Windows server has been rebooted and the manual routes have thus been reset.