Friday, August 10, 2018

Be careful out there!

I ran across something this week you should probably be aware of. I was checking my Spectrum modem was not set to default passwords. Spectrum seems to have stopped setting them up with the factory default passwords. (While bad for people like me that like to monitor signal strength and know the password is changed it is probably a plus over all given how few seem to change their modems and routers from the defaults.) Anyway I googled the common ones used to see if the one (or ones) Spectrum is using might be online. The first link returned took me a page that looked like useful logins to try. But then I started getting warnings that this page was trying to probe my network. Without a paranoid level of network threat management I might not have even known. Note one of things that set off alarms in my network was it was trying to use https avoid packet inspection which, due to cert mismatch, triggered warnings. Another was one of addresses it tried to probe was the router for a test network that while configured has no devices on it at the moment.

Who cares? Well this is how some newer threats are getting past your firewall to your networked devices. They run probes on your network looking for devices with known exploits that they can then turn into a back doors into your network to take control of even more of your devices and even set them up to monitor your traffic. Then of course there are the malware cryptominers that that suck all your CPU. For an example of the level of adventure see https://www.grc.com/SN/SN-675-Notes.pdf



Sunday, June 24, 2018

Use Windows WMI and Powershell to send data to Homeseer

For instance if you want to sent the average temperature or the CPU cores on your Windows PC to Homeseer virtual devices so you can trigger and action on temperature too high.
Create a user to use for updating if you do not already have one

Create a virtual device in Homeseer similar to this
Be sure and uncheck  "Do not update device last change time if device value does not change:"


Note -1 is set by script if it encounters and error getting data for the virtual

Create a script like the script below replacing
10.10.1.45 with your Homeseer IP address
wmi with the user you created
wmiPass with the password for the above user.
4570 with the ref ID of the virtual device you created

function Get-Temperature {
    $t = @( Get-WmiObject MSAcpi_ThermalZoneTemperature -Namespace "root/wmi" )
    $cores = 0
    $tempTotal=0
    foreach ($temp in $t)
    {
        $CORES += 1
        $currentTempKelvin = $temp.CurrentTemperature / 10
        $currentTempCelsius = $currentTempKelvin - 273.15
        $tempTotal += $currentTempCelsius 
        $currentTempFahrenheit = (9/5) * $currentTempCelsius + 32

        #write ($currentTempCelsius.ToString() + " C : " + $currentTempFahrenheit.ToString() + " F : " + $currentTempKelvin + "K")

    }
    return $tempTotal / $cores
}

$avgTemp=Get-Temperature


$url="http://10.10.1.45/JSON?user=wmi&pass=wmiPass&request=controldevicebyvalue&ref=4570&value=" + $avgTemp
#write ("avgTemp="+$avgTemp)
#write ("url="+$url)

(New-Object System.Net.WebClient).DownloadString($url);


My script is called cpuTemp.ps1 and is in C:\diags so I set up an task to run every hour (you can make it as often as every 5 minutes) like this.


Plus you probably want to set these

For more of a rounder picture with logging, here is a fuller script. Do not forget to change the highlighted bits.

## set these to your servers values
$Hs3ip="10.10.1.45"
$Hs3user="wmi"
$Hs3pass="wmiPass"
$tempRef="4570"
$loadRef="4577"
$pctFreeRef="4576"
$logLenRef="4593"
$updateRef="4594"
$Logfile = "C:\diags\$(gc env:computername).log"
## also update disk list in local drives at bottom

## if you need help figuring out why something is not working try
## removing # from any place you see #Write in the method with the problem.

$baseURL="http://"+$Hs3ip+"/JSON?user="+$Hs3user+"&pass="+$Hs3pass+"&request=controldevicebyvalue&ref="

## for even fancier logging see https://gist.github.com/barsv/85c93b599a763206f47aec150fb41ca0
Function Write-Log($Message) {

    $Stamp = (Get-Date).toString("yyyy/MM/dd HH:mm:ss")
    $Line = "$Stamp $Message"
    If($logfile) {
    ## to stop logging put a # in front of next line
        Add-Content $logfile -Value $Line
    }
    Else {
        Write-Output $Line
    }
}

function sendData($ref,$value) {
#write ("ref="+$ref)
#write ("value="+$value)
    $url=($baseURL+$ref+"&value="+$value)
    Write-Log ($url)
    $resp = (New-Object System.Net.WebClient).DownloadString($url);
    #write $resp
    $respObj = ConvertFrom-Json($resp)

    if (! $respObj.Name ) {
       Write-Error ("Error:"+ $resp)
       Write-Error ($url)
    }
    Write-Log ($resp)
}

function sendError($ref,$err) {
    Write-Error ("Error for:"+$ref+":"+$err)
    #Write-Log ($err)
    sendData $ref -1
}

function updateDiskFree($diskLetter,$diskRef) {
    try {
        $filter = "DeviceID='"+$diskLetter+"'"

        $disk = get-wmiobject -class "Win32_LogicalDisk" -namespace "root\CIMV2" -Filter "$filter" | Select-Object Size,FreeSpace
        $size = [math]::round($disk.Size/1GB, 2)
        $free = [math]::round($disk.FreeSpace/1GB, 2)
        $freePercent=[math]::round(($free/$size * 100), 2)
        #write ($diskLetter+" "+$diskRef+" size="+$size+" free="+$free+" free="+$freePercent+"%")

        sendData $diskRef $freePercent
    } catch {

        sendError $diskRef $_
    }
}

## other temp options:
## root\cimv2:Win32_TemperatureProbe CurrentReading
function Get-Temperature {
    try {
        $t = @( Get-WmiObject MSAcpi_ThermalZoneTemperature -Namespace "root/wmi" )
        #write $t
        $cores = 0
        $tempTotal=0
        foreach ($temp in $t)
        {
            $cores += 1
            $currentTempKelvin = $temp.CurrentTemperature / 10
            $currentTempCelsius = $currentTempKelvin - 273.15
            $tempTotal += $currentTempCelsius 
            $currentTempFahrenheit = (9/5) * $currentTempCelsius + 32

            Write-Log ("Core "+$cores+":"+$currentTempCelsius.ToString() + " C : " + $currentTempFahrenheit.ToString() + " F : " + $currentTempKelvin + "K")
        }
        sendData $tempRef ($tempTotal / $t.Count)
    } catch {
        sendError $tempRef $_
    }
}

Get-Temperature


## CPU load
try {
    $load=Get-WmiObject win32_processor | select LoadPercentage
    sendData $loadRef  $load.LoadPercentage
} catch {
    sendError $loadRef $_
}


## free RAM
try {
    $os = Get-Ciminstance Win32_OperatingSystem
    $pctFree = [math]::Round(($os.FreePhysicalMemory/$os.TotalVisibleMemorySize)*100,2)
    sendData $pctFreeRef $pctFree
} catch {
    sendError $pctFreeRef $_
}

## watch log length
try {
   #write (Get-Item $Logfile)
   $logLen = [math]::Round((Get-Item $Logfile).length / 1MB,3)
    sendData $logLenRef $logLen
} catch {
    sendError $logLenRef $_
}

## count updates pending
try {
    $UpdateSession = New-Object -ComObject Microsoft.Update.Session
    $UpdateSearcher = $UpdateSession.CreateupdateSearcher()
    ## does not want to filter on and DownloadPriority=2 or and DownloadPriority>1 so extra update is listed
    $Updates = @($UpdateSearcher.Search("IsHidden=0 and IsInstalled=0").Updates)
    $Updates| Select-Object Title,IsMandatory,IsDownloaded,RebootRequired,AutoSelection,AutoDownload,MsrcSeverity,DeploymentAction,DownloadPriority

    if ($Updates.Count > 1) {
        write ("Updates pending:"+ $Updates.Count)
    }
    sendData $updateRef $Updates.Count
} catch {
    sendError $updateRef $_
}

## local drives
updateDiskFree "C:" 4571
updateDiskFree "D:" 4572
updateDiskFree "E:" 4574
updateDiskFree "P:" 4573
## drobo
updateDiskFree "L:" 4578
##synology
updateDiskFree "Z:" 4579


Which looks like this


When I deployed to my second PC I found not even the Administrator could run scripts and had to set its policy to Bypass. See this Microsoft doc for more info on that.

Also the temperature readings are the same and unchanging on both PCs I've deployed to so far so they might not be useful despite all the posts out there claiming they are.