Server Scan Version 1

As part of current work projects we are being asked to profile servers here is a quick dirty script being used. Has several useful pieces.

 

$servers = import-csv \\ciwfsxxp0003\andrew\PowershellScripts\ServerMigFunctions\BPO_Policy\servers2.txt -Delimiter “,”
$output = “c:\temp\ServerPreScan.txt”
foreach ($server in $servers)
{
#Header
write-output “________________________________________________” | tee-object -filepath $output -append
write-output “————————–” | tee-object -filepath $output -append
write-output “—-$($server.ServerName) $($server.Application)”—- | tee-object -filepath $output -append
write-output “————————–” | tee-object -filepath $output -append
#Get OS Version we only care about server 2003
$windowsversion = (Get-WmiObject -class Win32_OperatingSystem -computer $server.ServerName).Caption
Write-Output $windowsversion | tee-object -filepath $output -append
#if the version is not 2003 no reason to continue this charade
if ($windowsversion -like “*2003*”) {
#Get Shares
write-output “————————–” | tee-object -filepath $output -append
write-output “—-Shares—-” | tee-object -filepath $output -append
get-WmiObject -class Win32_Share -computer $server.ServerName | tee-object -filepath $output -append

#Get Services note removing most standard services
(Get-WmiObject -class Win32_OperatingSystem).Caption
write-output “—-Services—-” | tee-object -filepath $output -append
get-WmiObject -class Win32_Service -computer $server.ServerName |
where { $_.Caption -notmatch “Windows” -and $_.PathName -notmatch “Windows” -and $_.PathName -notmatch “policyhost.exe” -and $_.Name -ne “LSM” `
-and $_.PathName -notmatch “OSE.EXE” -and $_.PathName -notmatch “OSPPSVC.EXE” -and $_.PathName -notmatch “Microsoft Security Client” `
-and $_.Pathname -notmatch “WINNT” [keep adding them here if you have some others] -and $_.state -eq “Running” } |
Format-Table Name,StartMode,State,Status, Pathname, Caption | tee-object -filepath $output -append

#Is the certain services installed
write-output “—-Connect Service—-” | tee-object -filepath $output -append
get-WmiObject -class Win32_Service -computer $server.ServerName |
where { $_.Caption -match “[service name]” -and $_.state -eq “Running” } |
Format-Table Name,StartMode,State,Status, Pathname, Caption |
tee-object -filepath $output -append

#get a list of websites
write-output “—-WebSites—-” | tee-object -filepath $output -append
Try{
Get-WmiObject -Namespace ROOT\microsoftiisv2 -Class IISWebServerSetting -ComputerName $server.ServerName -erroraction ‘silentlycontinue’ |
Format-Table Namespace,Name,ServerComment,AppPoolId |
tee-object -filepath $output -append
}Catch{
write-output “N/A” | tee-object -filepath $output -append
}

#check the bpo policy
write-output “—-BPO Policy—-” | tee-object -filepath $output -append
$Priv=Get-WMIObject -computername $server.ServerName RSOP_UserPrivilegeRight -namespace root\rsop\computer |
Where {$_.UserRight -eq “SeDenyNetworkLogonRight” } |
Select -expand AccountList
$RBY = “[account we care about denying access to]”
If ($Priv |select-string -pattern $RBY -simplematch)
{ $BPO = “NO” }
Else
{ $BPO = “YES”}
write-output $BPO | tee-object -filepath $output -append

#Get any odbc connections
write-output “—-odbc connections—-” | tee-object -filepath $output -append
$standardkeys=@(“[list of standard odbc keys we’ll find on the server to filter out]”)
$odbckey =”SOFTWARE\\odbc\\odbc.ini”
$reg=[microsoft.win32.registrykey]::OpenRemoteBaseKey(‘LocalMachine’,$server.ServerName)
$regkey=$reg.OpenSubKey($odbckey)
#Retrieve an array of string that contain all the subkey names
$subkeys=$regkey.GetSubKeyNames()
#Open each Subkey and use GetValue Method to return the required values for each
foreach($key in $subkeys){
# $thisKey=$odbckey+”\\”+$key
# $thisSubKey=$reg.OpenSubKey($thisKey)
if ($standardkeys -notcontains $key) { Write-Output $key | tee-object -filepath $output -append }
}

#Get any scheduled tasks exxcep w2k3 though there are others we can remove as well.
write-output “—-Scheduled Tasks—-” | tee-object -filepath $output -append
get-wmiobject -class “Win32_ScheduledJob” -namespace “root\CIMV2” -computername $server.ServerName |
Where { $_.Command -notmatch “E:\W2K3.bat” } |
Format-Table Caption, Command, Jobstatus |
tee-object -filepath $output -append
}
else
{
write-output “Nothing to do here. Kindly move along.” | tee-object -filepath $output -append
}
}

Posted in Powershell, Scripting, Uncategorized, wmi

Registry Reading and ODBC Reading

$standardkeys = @(#array of standard keys you might not wish to read#)

$odbckey =”SOFTWARE\\odbc\\odbc.ini”
$reg=[microsoft.win32.registrykey]::OpenRemoteBaseKey(‘LocalMachine’,$server.ServerName)
$regkey=$reg.OpenSubKey($odbckey)
#Retrieve an array of string that contain all the subkey names
$subkeys=$regkey.GetSubKeyNames()
#Open each Subkey and use GetValue Method to return the required values for each
foreach($key in $subkeys){
# $thisKey=$odbckey+”\\”+$key
# $thisSubKey=$reg.OpenSubKey($thisKey)
if ($standardkeys -notcontains $key) { Write-Output $key | tee-object -filepath $filelocation -append }
}

 

*Note on a 64 bit system might need to change the registry location.

Posted in Uncategorized

Things I Might Have Made to Difficult: Or getting a domain name for a host

So in a multi-domain environment you can be given a host-name without the host.  You can also be asked to write a script that might need to work in multiple domains where administrative passwords are not in sync. Hence the need to have your script figure out what domain your server is in.

Hence this little gem:

$server = ”
$hostipinfo=[System.Net.Dns]::GetHostByName($server)
$hostip = $hostipinfo.AddressList[0]
$hostdomaininfo=[System.Net.Dns]::GetHostByAddress($hostip)
$hostdomain = $hostdomaininfo.HostName
$hostdomain = $hostdomain.Replace(“$($server).”,””)

(Heaven help you if your server names are not unique across domain.)

Posted in Uncategorized

Hopefully an improved copy item

When there is an issue with Copy-Item because the directory does not exist when you are moving files.

function CopyItem
{
param
(
[Parameter()][string] $paramdestinationcomputer,
[Parameter()][string] $paramsource,
[Parameter()][string] $paramdestination
)
#ensure destination location exists
if ( $(Try { Test-Path $paramdestination.Trim() } Catch { $false }) ) {
Write-Output “$($paramdestination) Path OK” | Tee-Object -filepath $logfilepath -append
}
Else {
Write-Output “creating $($paramdestination) path” | tee-object -filepath $logfilepath -append
try {
New-Item -Path $paramdestination -type directory -Force -ErrorAction Stop
}
catch
{
$ErrorMessage = $_.Exception.Message
$FailedItem = $_.Exception.ItemName
Write-Output “We failed to create folder $FailedItem. The error message was $ErrorMessage” | tee-object -filepath $logfilepath -append
break
}
}
Write-Output “$($paramdestination) Path Created OK” | tee-object -filepath $logfilepath -append
#ensure source location exists
if ( $(Try { Test-Path $paramsource.Trim() } Catch { $false }) ) {
Write-Output “$($paramsource) Path OK” | Tee-Object -filepath $logfilepath -append
}
Else {
Write-Output “creating $($paramsource) path” | tee-object -filepath $logfilepath -append
try {
New-Item -Path $paramsource -type directory -Force -ErrorAction Stop
}
catch
{
$ErrorMessage = $_.Exception.Message
$FailedItem = $_.Exception.ItemName
Write-Output “We failed to create folder $FailedItem. The error message was $ErrorMessage” | tee-object -filepath $logfilepath -append
break
}
}
Write-Output “$($paramsource) Path Created OK” | tee-object -filepath $logfilepath -append
Write-Output “attempting to copy $($paramsource) to $($paramdestination)” -append
#get msi to server
#upgrade check the dm5 for insurance
#Get-FileHash $paramsource -Algorithm MD5
try
{
#write-host “Enter domain: Internal Admin Credentials”
# $internalcredentials = Get-Credential
Copy-Item $paramsource $paramdestination -Force -ErrorAction Stop #-Credential $internalcredentials
}
catch
{
$ErrorMessage = $_.Exception.Message
$FailedItem = $_.Exception.ItemName
Write-Output “We failed to create $FailedItem. The error message was $ErrorMessage” | tee-object -filepath $logfilepath -append
break
}
#need to validate that md5 here

Write-Output “wrote $($paramdestination) to $($server)” | tee-object -filepath $logfilepath -append
#end copy exe
}

Yes, it is possible I go a little bit off with error correction…

Posted in Uncategorized

Finding Installed Applications (or more ways to do stuff without wmi)

I’m not anti wmi by far but the second time I’ve had to come up with a faster way or more precise way to search for an installed app.

Keeping this one around for safe keeping.

$server=””
#registry location for app
#32 bit
$regpath=”SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall”
#64 bit
#$regpath=”SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall”
#open key
$reg=[microsoft.win32.registrykey]::OpenRemoteBaseKey(‘LocalMachine’,$server)
#look in registry
$regkey=$reg.OpenSubKey($regpath)
$subkeys=$regkey.GetSubKeyNames()
foreach($key in $subkeys){
$CurrentKey=$UninstallKey+”\\”+$key
$CurrentSubKey=$reg.OpenSubKey($CurrentKey)
#if you want to search for a certain key
# if ($CurrentSubKey.GetValue(“DisplayName”) -like “**”){
write-output $($CurrentSubKey.GetValue(“DisplayName”))
# }
}

Posted in InstalledApps, Powershell, Scripting, Uncategorized, wmi

Powershell and secedit

This is the starter for a script to get content from secedit.

Still ugly will finish it up next week I hope.  As you can tell it’s going to ultimately take several parameters. I cannot take full credit the function I found online and chose to use. I wish I could work regex on the fly that well.

Needs comments and error correction and some other general cleanup.

 

Param
(
[Parameter][string] $paramcomputer,
[Parameter][string] $paramseceditpath,
[Parameter][string] $paramoutfilepath,
[Parameter][string] $parampathtopsexec
)
function Get-SecContent ($file)
{
$Sec = @{}
switch -regex -file $File
{
“^\[(.+)\]” # Section
{
$section = $matches[1]
$Sec[$section] = @{}
$CommentCount = 0
}
“^(;.*)$” # Comment
{
$value = $matches[1]
$CommentCount = $CommentCount + 1
$name = “Comment” + $CommentCount
$Sec[$section][$name] = $value
}
“(.+?)\s*=(.*)” # Key
{
$name,$value = $matches[1..2]
$Sec[$section][$name] = $value
}
}
return $Sec
}
$currentdatetime=[int][double]::Parse((Get-Date -UFormat %s))
$server = ‘WDCINS016’
$seceditpath = “c:\temp\$($server)secedit$($currentdatetime).cfg”
$outfilepath = “$($server)outfile($currentdatetime).csv”
$pathtopsexec = “<full path>psexec.exe”
psexec.exe \\$($server) secedit /export /areas USER_RIGHTS /cfg $($seceditpath)
try
{
Copy-Item \\<server name>\c$\temp\$($server)secedit$($currentdatetime).cfg c:\temp\$($server)secedit$($currentdatetime).cfg -ErrorAction Stop
}
catch
{
$ErrorMessage = $_.Exception.Message
$FailedItem = $_.Exception.ItemName
Write-Host “We failed to read file $FailedItem. The error message was $ErrorMessage”
Break
}

$GI = ” | Select ‘MemberName’,’Privilege’
$SeceditWithMemberNames = @()
$SecContent = Get-SecContent $seceditpath
$SecContent[“Privilege Rights”].Keys | % {
$Priv = $_
$SIDS = $SecContent[“Privilege Rights”].Item($_).trim()
($SIDS.split(“,”)) | % {
$SID= $_
try {
$objSID = New-Object System.Security.Principal.SecurityIdentifier ($SID.substring(1))
$objUser = $objSID.Translate( [System.Security.Principal.NTAccount])
$Name = “$objUser”
} catch {
$Name = “$SID”
} # Catch
$GI.”Privilege” = $Priv
$GI.”MemberName” = $NAME
$SeceditWithMemberNames+= $GI | Select ‘MemberName’,’Privilege’
#md sid splits
}
#end keys loop
}
$SeceditWithMemberNames | Export-CSV $outfilepath -NoTypeInformation

Posted in Uncategorized

Management Tips from Herodotus P5

“Certainty, surely, is beyond human grasp.”

This I am betting is a tough one to get around.  We sure as heck like certainty and when we don’t have it we are troubled. But do we ever really have it?

Posted in Uncategorized

One is the Loneliest Number or Powershell and an API

Am I the only one who looks at a selfie on social media and thinks, “That person is so lonely. They have no one to take their picture.”  Then I see a selfie on LinkedIn and I feel really bad for that person. They can’t even get someone to help take a profile photo.  I  want to offer to help. Here is the start of a way to use the google API and powershell to find photographers in your area.

Also a in a slightly less snarky light. Here is PowerShell fun with API’s.

#method is either web or email

$method = ’email’

#get your own key

$key = #get your own key at code.google.com

$yourlocation = ‘Nashville TN’

$url = https://maps.googleapis.com/maps/api/place/textsearch/json?query=photagrapher+in+$($yourlocation)&key=$($key)”

write-host $url

if ($method -eq ‘web’) {

    start $url

    }

    elseif ($method -eq ’email’){

     #$text2 = (Invoke-WebRequest $url).content

     #write-host $text2

     $text  Invoke-RestMethod -Uri $url

     $text | Select -ExpandProperty results | Select name,formatted_address,place_id | foreach{

 #This part still needs a little help.

       $detailsurl = https://maps.googleapis.com/maps/api/place/details/json?placeid=$($_.place_id)&key=$($key)”

        write-host $detailsurl

        write-host “Place_Id: $($_.place_id)”

        write-host “Name: $($_.name)”

        write-host “Address: $($_.formatted_address)”

        #$text1 = Invoke-RestMethod -Uri $detailsurl 

        #try {

        #    $text1 | Select -ExpandProperty result | Select formatted_phone_number,website | fl

        #    }catch{

        #    write-host “Number not found “

        #    }

        $text2 = (Invoke-WebRequest $detailsurl).content

        write-host $text2 

        }

    }   else { write-host ‘use method web or email’ }

It’s powershell and a little incomplete. But it does show how powershell can interact with api’s which is a ton of fun.  I’ll have to have some more fun with the PowerShell in the final version it is really rather boring right now.

Also if your profile photo is a selfie you normally look a little distorted, it’s not you, it’s the way selfies look.

Posted in API, Powershell, Scripting, Selfie, Selfies

Quotes that make you hmmm….

I love any sentence that you have to really think about…

From QBQ by John G. Miller

“Leaders are not problem solvers, but problem givers.”

If your first thought on that is negative, think some more.

Posted in Uncategorized

Management Tips from Herodotus P4

“I would never much rather take a risk and run into trouble half the time than keep out of trouble through being afraid of everything.”

As I move to Cigna and start a new position.

Posted in Greek, Herodotus, Leadership, Management, Uncategorized