' Network Discovery Script
' Author: Richard McFarland (richard@cervisys.com)
' First release: 7/31/09
' =============================================
' Scans through IP addresses and does reverse DNS lookup report, Windows basic configuration report,
' and Active Directory report
Dim objExplorer, txtOutput, fs, ResFile, CSVFile, SrvFile, DTFile, startAddress, numberAddresses, binScanAD
Dim binScanIP
ReDim arrDupName(0)
const crlf="
"
Setup
If binScanIP = True Then
LoopSearch
End If
If binScanAD = True Then
getADInfo
End If
showText(crlf & "Finished!")
'Wscript.Sleep 10000
'objExplorer.Quit
Sub LoopSearch
'Break down the IP
IP = Split(startAddress, ".")
If IP(3) = 0 then IP(3) = 1
For loopIP = 1 to numberAddresses
tmpIP = Join(IP, ".")
ResPing = Ping(tmpIP)
If ResPing = "Failed" then
ResParsed = "No Response"
Else
If IsNull(ResPing) or ResPing = "" or ResPing = tmpIP then
ResParsed = "Ping Response, No Name Resolution"
Else
ResParsed = ResPing
discoverDevice ResParsed
End If
End If
writeTxt tmpIP, ResParsed
IP(3) = IP(3) + 1
For i = 3 to 0 Step - 1
If IP(i) > 254 and i > 1 then
IP(i) = 1
IP(i - 1) = IP(i - 1) + 1
Else
If IP(1) > 254 then
showText("Inputted IP range ran past valid IP range")
wscript.Quit(0)
End If
End If
Next
Next
ResFile.Close
CSVFile.Close
SrvFile.Close
DTFile.Close
End Sub
Function Ping(strHost)
Dim objPing, objRetStatus
showText("Pinging " & strHost & "...")
Set objPing = GetObject("winmgmts:{impersonationLevel=impersonate}").ExecQuery("select * from Win32_PingStatus where address = '" & strHost & "' AND ResolveAddressNames = TRUE")
For Each objRetStatus in objPing
If IsNull(objRetStatus.StatusCode) or objRetStatus.StatusCode <> 0 then
Ping = "Failed"
Else
Ping = objRetStatus.ProtocolAddressResolved
End if
Next
Set objPing = Nothing
End Function
Function prepSize(numSize)
if numSize > 0 then
numSize = (numSize / 1024) / 1024
strMem = "MB"
If numSize > 1000 then
strMem = "GB"
numSize = numSize / 1024
End If
numSize = round(numSize, 2)
prepSize = numSize & " " & strMem
Else
PrepSize = ""
End If
End Function
Sub Setup
Set objExplorer = WScript.CreateObject("InternetExplorer.Application")
objExplorer.Navigate "about:blank"
objExplorer.ToolBar = 0
objExplorer.StatusBar = 0
objExplorer.Width = 400
objExplorer.Height = 200
objExplorer.Left = 100
objExplorer.Top = 100
Do While (objExplorer.Busy)
Wscript.Sleep 200
Loop
objExplorer.Visible = 1
txtOutput=""
Set fs = CreateObject ("Scripting.FileSystemObject")
Set ResFile = fs.CreateTextFile (".\IPDevices.txt")
writeTxtLine("IP Address Node Name")
writeTxtLine("==============================================================")
writeTxtLine("")
Set CSVFile = fs.CreateTextFile (".\IPDevices.csv")
CSVFile.WriteLine "IP Address,Host"
Set SrvFile = fs.CreateTextFile (".\WindowsServerList.csv")
SrvFile.WriteLine "Computer,Make/Model,Service Tag,Serial Number,OS,Processor,RAM,Hard Drives"
Set DTFile = fs.CreateTextFile (".\WindowsDesktopList.csv")
DTFile.WriteLine "Computer,Make/Model,Service Tag,Serial Number,OS,Processor,RAM,Hard Drives"
Set readFile = fs.OpenTextFile (".\nd.ini")
Do Until readFile.AtEndOfStream
strLine = readFile.ReadLine
If InStr(strLine, "=") > 0 Then
strValue = Trim(Right(strLine, Len(strLine) - InStr(strLine, "=")))
Else
strValue = ""
End If
If UCase(Left(strLine, 9)) = "IPADDRESS" Then
strIP = strValue
End If
If UCase(Left(strLine, 10)) = "SUBNETMASK" Then
strMask = strValue
End If
If UCase(Left(strLine, 8)) = "NUMNODES" Then
numNodes = strValue
End If
If UCase(Left(strLine, 6)) = "SCANIP" Then
If UCASE(strValue) = "YES" or UCASE(strValue) = "TRUE" or strValue = "1" Then
binScanIP = TRUE
Else
binScanIP = FALSE
End If
End If
If UCase(Left(strLine, 6)) = "SCANAD" Then
If UCASE(strValue) = "YES" or UCASE(strValue) = "TRUE" or strValue = "1" Then
binScanAD = TRUE
Else
binScanAD = FALSE
End If
End If
Loop
If IsNull(numNodes) or numNodes = "" then numNodes = 0
If numNodes <= 0 Then
startAddress = CalcRangeStart(strIP, strMask)
numberAddresses = MaskLength(strMask)
numberAddresses = GetNumberOfAvailableHostAddresses(numberAddresses)
Else
startAddress = strIP
numberAddresses = numNodes
End If
End Sub
Sub ShowText(txtInput)
txtOutput = "Network Discovery In Progress:" & crlf & "==================================" & crlf
txtOutput = txtOutput & txtInput
objExplorer.Document.Body.InnerHTML = txtOutput
End Sub
Sub writeTxt(txtIP, txtRes)
strPad = "............................"
CSVFile.WriteLine chr(34) & txtIP & chr(34) & "," & chr(34) & txtRes & chr(34)
ResFile.WriteLine (txtIP & Left(strPad, 29 - Len(txtIP)) & txtRes)
End Sub
Sub writeTxtLine(txtInput)
ResFile.WriteLine txtInput
End Sub
Sub discoverDevice(strDeviceName)
On Error Resume Next
Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strDeviceName & "\root\cimv2")
If Err.Number <> 0 Then
Err.Clear
On Error Goto 0
Else
On Error Goto 0
Set colItems = objWMIService.ExecQuery("Select * from Win32_OperatingSystem")
For Each objItems in colItems
strHost = objItems.CSName
strOS = Trim(objItems.Caption)
If (InStr(strOS, "200") or InStr(UCase(strOS), "W")) > 0 then
bIsNT = False
strOSSP = Trim(objItems.ServicePackMajorVersion & "." & objItems.ServicePackMinorVersion)
Else
bIsNT = True
strOSSP = "."
End If
If strOSSP <> "." then
strOS = strOS & " SP: " & strOSSP
End If
Next
'wscript.echo strOS
Set colItems = Nothing
If InStr(UCase(strOS), "W") > 0 then
Set colItems = objWMIService.ExecQuery("Select * from Win32_Processor")
numCPUs = 0
For Each objItems in colItems
numCPUs = NumCPUs + 1
strCPUName = Trim(objItems.Name)
Next
Set colItems = Nothing
bFound = False
For i = 1 to UBound(arrDupName)
If UCase(arrDupName(i)) = UCase(strHost) then
bFound = True
Exit For
End If
Next
If bFound = False then
showText("Auditing " & strHost & "...")
i = UBound(arrDupName) + 1
ReDim Preserve arrDupName(i)
arrDupName(i) = strHost
strTemp = ""
If numCPUs > 1 then
strTemp = "(" & numCPUs & ") "
End If
strCPUName = strTemp & strCPUName
'Get Computer Info
If bIsNT = False then
Set colItems = objWMIService.ExecQuery("Select * from Win32_BaseBoard")
For Each objItem in colItems
strMakeModel = Trim(objItem.Manufacturer) & " " & Trim(objItem.Model)
strServiceTag = Trim(objItem.Product)
strSN = Trim(objItem.SerialNumber)
Next
set colItems = Nothing
'Get Memory Info
Set colItems = objWMIService.ExecQuery("Select * from Win32_PhysicalMemory")
numMemCap = 0
For Each objItem in colItems
numMemCap = numMemCap + objItem.Capacity
Next
strRAM = prepSize(numMemCap)
set colItems = Nothing
End If
'Get Logical Drive Info
Set colItems = objWMIService.ExecQuery("Select * from Win32_LogicalDisk")
strHardDrive = ""
t = 0
For Each objItem in colItems
If objItem.DriveType = 3 then
t = t + 1
If t > 1 then
strHardDrive = strHardDrive & ","
End If
strHardDrive = strHardDrive & chr(34) & objItem.Name & " " & prepSize(objItem.Size) & " (" & prepSize(objItem.FreeSpace) & " free)" & chr(34)
End If
Next
Set colItems = Nothing
'Save Line to text file
strLine = chr(34) & strHost & chr(34) & "," & chr(34) & strMakeModel & chr(34) & "," & chr(34) & strServiceTag & chr(34) & "," & chr(34) & strSN & chr(34) & "," & chr(34) & strOS & chr(34) & "," & chr(34) & strCPUName & chr(34) & "," & chr(34) & strRAM & chr(34) & "," & strHardDrive
If InStr(UCase(strOS), "SERVER") > 0 then
SrvFile.WriteLine strLine
Else
DTFile.WriteLine strLine
End If
Else
Set colItems = Nothing
End If
End If
Set objWMIService = Nothing
End If
End Sub
Sub getADInfo
ShowText("Getting Active Directory Information...")
Set ADFile = fs.CreateTextFile ("./AD Information.txt")
On Error Resume Next
Set objRootDSE = GetObject("LDAP://RootDSE")
If Err.Number = 0 then
on Error Goto 0
strConfig = objRootDSE.Get("configurationNamingContext")
'Determine AD Name
Set WSHNetwork = CreateObject("WScript.Network")
strDomain = WSHNetwork.UserDomain
Set WSHNetwork = Nothing
ADFile.WriteLine "Domain Name: " & strDomain
ADFile.WriteLine
ADFile.WriteLine
'Determine AD Sites
strSitesContainer = "LDAP://cn=Sites," & strConfig
Set objSitesContainer = GetObject(strSitesContainer)
objSitesContainer.Filter = Array("site")
ADFile.WriteLine "AD Sites:"
For Each objSite In objSitesContainer
ADFile.WriteLine " Site Name: " & removeCN(objSite.Name)
Next
ADFile.WriteLine
ADFile.WriteLine
'Find Domain Controllers
' Use ADO to search Active Directory for ObjectClass nTDSDSA.
Set objCommand = CreateObject("ADODB.Command")
Set objConnection = CreateObject("ADODB.Connection")
objConnection.Provider = "ADsDSOObject"
objConnection.Open "Active Directory Provider"
objCommand.ActiveConnection = objConnection
strQuery = ";(ObjectClass=nTDSDSA);AdsPath;subtree"
objCommand.CommandText = strQuery
objCommand.Properties("Page Size") = 100
objCommand.Properties("Timeout") = 30
objCommand.Properties("Cache Results") = False
Set objRecordSet = objCommand.Execute
' The parent object of each object with ObjectClass=nTDSDSA is a Domain
' Controller. The parent of each Domain Controller is a "Servers"
' container, and the parent of this container is the "Site" container.
ADFile.WriteLine "Domain Controllers:"
i = 0
ReDim arrDC(0)
Do Until objRecordSet.EOF
i = i + 1
ReDim Preserve arrDC(i)
Set objDC = GetObject(GetObject(objRecordSet.Fields("AdsPath")).Parent)
Set objSite = GetObject(GetObject(objDC.Parent).Parent)
arrDC(i) = objDC.cn
ADFile.WriteLine " DC: " & removeCN(objDC.cn)
ADFile.WriteLine " Site: " & removeCN(objSite.Name)
ADFile.WriteLine
objRecordSet.MoveNext
Loop
ADFile.WriteLine
ADFile.WriteLine
' Clean up.
objConnection.Close
Set objCommand = Nothing
Set objConnection = Nothing
Set objRecordSet = Nothing
Set objDC = Nothing
Set objSite = Nothing
ADFile.WriteLine "FSMO Role Holders:"
'Schema Master
Set objSchema = GetObject("LDAP://" & objRootDSE.Get("schemaNamingContext"))
strSchemaMaster = objSchema.Get("fSMORoleOwner")
Set objNtds = GetObject("LDAP://" & strSchemaMaster)
Set objComputer = GetObject(objNtds.Parent)
ADFile.WriteLine " Forest-wide Schema Master FSMO: " & removeCN(objComputer.Name)
Set objNtds = Nothing
Set objComputer = Nothing
'Domain Naming Master
Set objPartitions = GetObject("LDAP://CN=Partitions," & objRootDSE.Get("configurationNamingContext"))
strDomainNamingMaster = objPartitions.Get("fSMORoleOwner")
Set objNtds = GetObject("LDAP://" & strDomainNamingMaster)
Set objComputer = GetObject(objNtds.Parent)
ADFile.WriteLine " Forest-wide Domain Naming Master FSMO: " & removeCN(objComputer.Name)
Set objNtds = Nothing
Set objComputer = Nothing
'PDC Emulator
Set objDomain = GetObject("LDAP://" & objRootDSE.Get("defaultNamingContext"))
strPdcEmulator = objDomain.Get("fSMORoleOwner")
Set objNtds = GetObject("LDAP://" & strPdcEmulator)
Set objComputer = GetObject(objNtds.Parent)
ADFile.WriteLine " Domain's PDC Emulator FSMO: " & removeCN(objComputer.Name)
Set objNtds = Nothing
Set objComputer = Nothing
'RID Master
Set objRidManager = GetObject("LDAP://CN=RID Manager$,CN=System," & objRootDSE.Get("defaultNamingContext"))
strRidMaster = objRidManager.Get("fSMORoleOwner")
Set objNtds = GetObject("LDAP://" & strRidMaster)
Set objComputer = GetObject(objNtds.Parent)
ADFile.WriteLine " Domain's RID Master FSMO: " & removeCN(objComputer.Name)
Set objNtds = Nothing
Set objComputer = Nothing
'Infrastructure Master
Set objInfrastructure = GetObject("LDAP://CN=Infrastructure," & objRootDSE.Get("defaultNamingContext"))
strInfrastructureMaster = objInfrastructure.Get("fSMORoleOwner")
Set objNtds = GetObject("LDAP://" & strInfrastructureMaster)
Set objComputer = GetObject(objNtds.Parent)
ADFile.WriteLine " Domain's Infrastructure Master FSMO: " & removeCN(objComputer.Name)
Set objNtds = Nothing
Set objComputer = Nothing
ADFile.WriteLine
ADFile.WriteLine
Set objRootDSE = Nothing
'Find GC's
Const NTDSDSA_OPT_IS_GC = 1
ADFile.WriteLine "Global Catalogs:"
On Error Resume Next
For i = 1 to UBound(arrDC)
Set objRootDSE = GetObject("LDAP://" & arrDC(i) & "/rootDSE")
strDsServiceDN = objRootDSE.Get("dsServiceName")
Set objDsRoot = GetObject("LDAP://" & arrDC(i) & "/" & strDsServiceDN)
intOptions = objDsRoot.Get("options")
If intOptions And NTDSDSA_OPT_IS_GC Then
ADFile.WriteLine " " & arrDC(i)
End If
Next
Set objDsRoot = Nothing
Set objRootDSE = Nothing
Else
ADFile.WriteLine
ADFile.WriteLine "No Active Directory domain found."
End If
on Error Goto 0
ADFile.Close
End Sub
Sub quickText(strInput)
txtOutput = txtOutput & strInput
objExplorer.Document.Body.InnerHTML = txtOutput
End Sub
Function ConvertIPToBinary(strIP)
' Converts an IP Address into Binary
Dim arrOctets
Dim strBinOctet
Dim intOctet, i, j
arrOctets = Split(strIP, ".")
For i = 0 to UBound(arrOctets)
intOctet = CInt(arrOctets(i))
strBinOctet = ""
For j = 0 To 7
If intOctet And (2^(7 - j)) Then
strBinOctet = strBinOctet & "1"
Else
strBinOctet = strBinOctet & "0"
End If
Next
arrOctets(i) = strBinOctet
Next
ConvertIPToBinary = Join(arrOctets, ".")
End Function
Function ConvertBinIPToDecimal(strBinIP)
' Convert binary form of an IP back to decimal
Dim arrOctets
Dim intOctet, i, j
arrOctets = Split(strBinIP, ".")
For i = 0 to UBound(arrOctets)
intOctet = 0
For j = 0 to 7
intBit = CInt(Mid(arrOctets(i), j + 1, 1))
If intBit = 1 Then
intOctet = intOctet + 2^(7 - j)
End If
Next
arrOctets(i) = CStr(intOctet)
Next
ConvertBinIPToDecimal = Join(arrOctets, ".")
End Function
Function CalcRangeStart(strIP, strMask)
' Generates the Network Address from the IP and Mask
Dim arrOctets
Dim strBinIP, strBinMask, strIPBit, strMaskBit, strBinStart
Dim intOctet, i, j
' Conversion of IP and Mask to binary
strBinIP = ConvertIPToBinary(strIP)
strBinMask = ConvertIPToBinary(strMask)
' Bitwise AND operation (except for the dot)
For i = 1 to Len(strBinIP)
strIPBit = Mid(strBinIP, i, 1)
strMaskBit = Mid(strBinMask, i, 1)
If strIPBit = "1" And strMaskBit = "1" Then
strBinStart = strBinStart & "1"
ElseIf strIPBit = "." Then
strBinStart = strBinStart & strIPBit
Else
If i = Len(strBinIP) Then
strBinStart = strBinStart & "1"
Else
strBinStart = strBinStart & "0"
End If
End If
Next
' Conversion of Binary IP to Decimal
CalcRangeStart = ConvertBinIPToDecimal(strBinStart)
End Function
Function GetNumberOfAvailableHostAddresses(numMaskLength)
numHosts = -1
numAvailableBits = 32 - numMaskLength
'Number of Addresses Available for Hosts in Subnet = 2(32 – Number of Masked Bits) – 2
numHosts = (2 ^ numAvailableBits) - 2
If numHosts < 0 then numHosts = 2
GetNumberOfAvailableHostAddresses = numHosts - 1
End Function
Function MaskLength(strMask)
' Converts an subnet mask into a mask length in bits
Dim arrOctets
Dim intOctet, intMaskLength, i, j
arrOctets = Split(strMask, ".")
For i = 0 to UBound(arrOctets)
intOctet = CInt(arrOctets(i))
For j = 0 To 7
If intOctet And (2^(7 -j)) Then
intMaskLength = intMaskLength + 1
End If
Next
Next
MaskLength = intMaskLength
End Function
Function removeCN(strName)
removeCN = Replace(strName, "CN=", "")
End Function