Author Posts

January 1, 2012 at 12:00 am

by the_hutch at 2013-01-25 07:08:21

So I'm running into a very unusual problem. I've developed a discovery script for an Air Force vulnerability management package. It gathers information from all systems on the network and then outputs the information to a CSV file. When I run it from a server machine (specifically Windows Server 2008 & Server 2008 R2), it returns an empty CSV file. I obviously have write access to the directory, because the CSV file is created. It just comes back empty. But run the exact same script from a client OS and it works without problem. Any thoughts?

by Klaas at 2013-01-25 07:14:29

My thought is that it's very difficult to troubleshoot a script that I can't see.
I'm doing similar things daily (of course nothing Air Force related) and everything works fine from both servers and clients.

by the_hutch at 2013-01-25 09:05:14

When running the script, it displays the output. However, once completed, it is just exporting an empty CSV. Once again, it works on any Windows 7 system I've tried it on. It is only on the servers that I'm having problems...

Here is the script:


##Removes error codes from output
$ErrorActionPreference = "silentlycontinue"

##Pre Clean-up
Get-Job | Stop-Job
Get-Job | Remove-Job

(1..4) | ForEach-Object {
IF ((Test-Path -Path "C:\discovery\Range$_.txt") -eq $True)
{
rm "C:\discovery\Range$_.txt"
}
}
IF ((Test-Path -Path "C:\discovery\pingtrace.txt") -eq $True) {rm "C:\pinger\pingtrace.txt"}

##Sets directory to be run from
cd C:\discovery\

$Pinger1 = {cmd.exe /c start cmd /k "C:\discovery\pinger.exe 172.16.0.0-172.16.255.255 -h C:\discovery\Range1.txt"}
$Pinger2 = {cmd.exe /c start cmd /k "C:\discovery\pinger.exe 172.17.0.0-172.17.255.255 -h C:\discovery\Range2.txt"}
$Pinger3 = {cmd.exe /c start cmd /k "C:\discovery\pinger.exe 172.18.0.0-172.18.255.255 -h C:\discovery\Range3.txt"}
$Pinger4 = {cmd.exe /c start cmd /k "C:\discovery\pinger.exe 172.19.0.0-172.19.255.255 -h C:\discovery\Range4.txt"}

Start-Job -ScriptBlock $Pinger1
Start-Job -ScriptBlock $Pinger2
Start-Job -ScriptBlock $Pinger3
Start-Job -ScriptBlock $Pinger4

WHILE (!((Test-Path -Path "C:\discovery\Range1.txt") -and (Test-Path -Path "C:\discovery\Range2.txt") -and (Test-Path -Path "C:\discovery\Range3.txt") -and (Test-Path -Path "C:\discovery\Range4.txt"))) {Start-Sleep 5}

Get-Process cmd | Stop-Process

##Uses the output files from each of the pinger scans to create independent arrays for each of the 4 ranges
$RangeList1 = Get-Content .\Range1.txt
$RangeList2 = Get-Content .\Range2.txt
$RangeList3 = Get-Content .\Range3.txt
$RangeList4 = Get-Content .\Range4.txt

(1..4) | ForEach-Object { IF ((Test-Path -Path "C:\discovery\Range$_.txt") -eq $True) {rm "C:\discovery\Range$_.txt"} }
IF ((Test-Path -Path "C:\pinger\pingtrace.txt") -eq $True) {rm "C:\pinger\pingtrace.txt"}
IF ((Test-Path -Path "C:\discovery\Discovery_Output.csv") -eq $True) {rm "C:\discovery\Discovery_Output.csv"}

##Defines the discovery tasks performed on each IP in each range passed to the script block
$job = {
param($Range)
($Range) | ForEach-Object -Process { $IP = "$_"
##Wiping variables
$strNS = $null
$strNBT = $null
$A1 = $null
$A2 = $null
$A3 = $null
$S1 = $null
$FQDN = $null
$NSHost = $null
$MAC = $null
$NBTHost = $null
$A4 = $null

##Run nslookup and nbtstat commands and assigns output to strings
[string]$strNS = nslookup $IP
[string]$strNBT = nbtstat -A $IP

##Gets hostname and FQDN from nslookup
IF($strNS -like '*Name*')
{
$A1 = $strNS.Split(":")
$S1 = $A1[3]
$A2 = $S1.Split(" ")
$FQDN = $A2[4]
$A3 = $FQDN.Split(".")
$NSHost = $A3[0]
}
ELSE
{
$NSHost = $null
$FQDN = $null
}
IF(!($FQDN -eq $null))
{
$FQDNArray = $FQDN.split(".")

##Gets MAC address and hostname from nbtstat
IF($strNBT -like '*Host not found*')
{
$MAC = $null
$NBTHost = $null
}
ELSE
{
$A1 = $strNBT.Split("=")
$S1 = $A1[1]
$A2 = $S1.Split(" ")
$PreMAC = $A2[1]
$MAC = $PreMAC.Replace("-",":")

$A3 = $strNBT.Split("< ")
IF ($A3[1] -like "20*")
{
$A4 = $A3[0].Split(' ')
[string]$NBTHost = $A4[73]
}
ELSEIF ($A3[2] -like "20*")
{
$A4 = $A3[1].Split(' ')
[string]$NBTHost = $A4[15]
}
ELSEIF ($A3[3] -like "20*")
{
$A4 = $A3[2].Split(' ')
[string]$NBTHost = $A4[15]
}
ELSEIF ($A3[4] -like "20*")
{
$A4 = $A3[3].Split(' ')
[string]$NBTHost = $A4[15]
}
ELSEIF ($A3[5] -like "20*")
{
$A4 = $A3[4].Split(' ')
[string]$NBTHost = $A4[15]
}
ELSEIF ($A3[6] -like "20*")
{
$A4 = $A3[5].Split(' ')
[string]$NBTHost = $A4[15]
}
ELSEIF ($A3[7] -like "20*")
{
$A4 = $A3[6].Split(' ')
[string]$NBTHost = $A4[15]
}
ELSEIF ($A3[8] -like "20*")
{
$A4 = $A3[7].Split(' ')
[string]$NBTHost = $A4[15]
}
ELSE
{
$NBTHost = $Null
}
}
}

##Defines output format for each unique IP address queried
$all="$IP`t$NSHost`t$NBTHost`t$MAC`t$FQDN"

##Write individual entry to final output
Write-Output "$all"
}
}

##Splits each of the 4 arrays of pingable IPs into 5 evenly divided sub-arrays
($RangeList1, $RangeList2, $RangeList3, $RangeList4) | ForEach-Object -Process {
$Range = $_
$Rangelen = $Range.length
$Rangediv = $Rangelen / 5
$RangeMult = [math]::floor($Rangediv)
$Mult1 = $RangeMult
$Mult2 = ($RangeMult * 2)
$Mult3 = ($RangeMult * 3)
$Mult4 = ($RangeMult * 4)
$Mult5 = ($Rangelen)
$Range1 = $Range[0..$Mult1]
$Range2 = $Range[($Mult1+1)..$Mult2]
$Range3 = $Range[($Mult2+1)..$Mult3]
$Range4 = $Range[($Mult3+1)..$Mult4]
$Range5 = $Range[($Mult4+1)..$Mult5]

##Executes 5 threads for each of the 4 ranges using the previously defined discovery process
Start-Job -ScriptBlock $job -Name "Discovery" -ArgumentList (,$Range1)
Start-Job -ScriptBlock $job -Name "Discovery" -ArgumentList (,$Range2)
Start-Job -ScriptBlock $job -Name "Discovery" -ArgumentList (,$Range3)
Start-Job -ScriptBlock $job -Name "Discovery" -ArgumentList (,$Range4)
Start-Job -ScriptBlock $job -Name "Discovery" -ArgumentList (,$Range5)
}

[array]$Output = "IP`tDNS HostName`tNetBIOS HostName`tMAC Address`tFQDN"

While (Get-Job -State "Running")
{
Get-Job | Receive-Job -keep
$Output = $Output + (Get-Job | Receive-Job)
Start-Sleep 1
}

#Stores output in variable and then exports to CSV file
Out-File -FilePath "Discovery_Output.csv" -Append -InputObject $Output

Write-Host "-- DISCOVERY COMPLETE --"
Write-Host "Output file (Discovery_Output.csv) will be located in C:\discovery\"
Write-Host "Please press ENTER to close script"
Read-Host

by sunnyc7 at 2013-01-25 15:12:24

Modifications Line 188 and below.
Delete this part
[code2=powershell]#Stores output in variable and then exports to CSV file
Out-File -FilePath "Discovery_Output.csv" -Append -InputObject $Output

Write-Host "– DISCOVERY COMPLETE –"
Write-Host "Output file (Discovery_Output.csv) will be located in C:\discovery\"
Write-Host "Please press ENTER to close script"
Read-Host[/code2]


Replace the part with

$output


save the script as script.ps1
Call the script like .\script.ps1 | out-file Discovery_Output.csv

by Klaas at 2013-01-26 11:44:15

Justin

I'm not 100% sure and I can't test untill monday, but I think the -append switch wasn't available in Powershell V 1 and 2, unless you had extra functions like Dmitry Sotnikov's
http://dmitrysotnikov.wordpress.com/2010/01/19/export-csv-append/
Is it possible you're working with version 3 on the Win7 machines while the Servers have PS version 2?