-
-
Save ion-storm/1f0b348cab881e789e89a8d9c203cbc7 to your computer and use it in GitHub Desktop.
Checks each server in the list of given computers for non-System accounts used in services and non-Microsoft scheduled tasks
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function Get-ServiceAccounts | |
{ | |
<# | |
.SYNOPSIS | |
Reaches out to the given servers to get service accounts used in services and scheduled tasks | |
.DESCRIPTION | |
Checks each server in the list of given computers for non-System accounts used in services and non-Microsoft scheduled tasks | |
.EXAMPLE | |
Get-ServiceAccounts -ComputerName "SERVER1","SERVER2" -CSV | |
.NOTES | |
Britt Thompson | |
[email protected] | |
.LINK | |
https://gist.github.com/automationhaus/063700ed973fc9ab8a560172994f56f8 | |
#> | |
[CmdletBinding()] | |
param | |
( | |
[Parameter(ValueFromPipelineByPropertyName=$true,Position=0)] | |
[Alias("CN","Computers","Servers")] | |
[string[]]$ComputerName = $env:COMPUTERNAME, | |
[switch]$CSV | |
) | |
Begin | |
{ | |
#region FUNCTIONS | |
function Write-Tee | |
{ | |
<# | |
.SYNOPSIS | |
Write output to the screen and to file simultaneously | |
.DESCRIPTION | |
Simply write your screen output to a file with automatic coloring based with special sytax between square brackets. Enable debugging and produce debugging only ouptut. | |
.EXAMPLE | |
Write-Tee "[=] This is the first task in my loop" | |
.EXAMPLE | |
Write-Tee @" | |
Write a long message without a prefix and overwrite your log file | |
"@ -NoPrefix -Overwrite | |
.EXAMPLE | |
Write-Tee "[?] Collect info without a line break" -NoNewLine; Read-Host | |
#> | |
[cmdletbinding()] | |
param | |
( | |
[Parameter(Position=0,ValueFromPipeline=$true)] | |
[string]$msg, | |
[string]$ForegroundColor = "White", | |
[string]$OutFile=$LogFile, | |
[switch]$Overwrite, | |
[switch]$NoNewLine, | |
[string]$Prefix=" - ", | |
[switch]$NoPrefix | |
) | |
$Info = "i"; $Task = "="; $Errors = "!"; $Inquiry = "?"; $Debugging = "d"; $Response = "r" | |
if($ForegroundColor -eq "") { $ForegroundColor = "White" } | |
$DBG = $False | |
switch -regex ($msg) | |
{ | |
"\[$Info\]" { $ForegroundColor = "Yellow" } | |
"\[$Task\]" { $ForegroundColor = "Cyan"; $Prefix = " " } | |
"\[$Errors\]" { $ForegroundColor = "Red" } | |
"\[\$Inquiry\]" { $ForegroundColor = "Magenta" } | |
"\[$Debugging\]" { $ForegroundColor = "Magenta"; $DBG = $True } | |
"\[$Response\]" { if($ForegroundColor -eq "White"){ $ForegroundColor = "Green" } } | |
default { $ForegroundColor = "White" } | |
} | |
if(($DBG -eq $False) -or ($DBG -and $Debug)){ $Write = $True } | |
if(!$NoPrefix) | |
{ | |
if($Write){ Write-Host $Prefix -NoNewline } | |
} | |
if($NoNewLine) | |
{ | |
if($Write){ Write-Host -ForegroundColor $ForegroundColor $msg -NoNewline } | |
} | |
else | |
{ | |
if($Write){ Write-Host -ForegroundColor $ForegroundColor $msg } | |
} | |
if(!$NoPrefix -and $msg -ne ""){ $msg = $Prefix + $msg } | |
if($OutFile -ne "") | |
{ | |
if(!$Overwrite) | |
{ | |
if($NoNewLine) | |
{ | |
if($Write){ [System.IO.File]::AppendAllText($OutFile, $msg, [System.Text.Encoding]::Unicode) } | |
} | |
else | |
{ | |
if($Write){ $msg | Out-File $OutFile -Append } | |
} | |
} | |
else | |
{ | |
if($Write){ $msg | Out-File $OutFile -Force } | |
} | |
} | |
} | |
function Get-Catch { Write-Tee "[!] $($_.Exception.Message)" } | |
#endregion | |
#region VARS | |
$ErrorActionPreference = "Stop" | |
$OSVersion = [decimal]([environment]::OSVersion.Version.Major,[environment]::OSVersion.Version.Minor -join ".") | |
# Define the script path based on the PowerShell version | |
if($PSVersionTable.PSVersion.Major -lt 3) | |
{ | |
$ScriptPath = Split-Path $Script:MyInvocation.MyCommand.Path -Parent | |
} else { $ScriptPath = $PSScriptRoot } | |
[string]$DateFormat = Get-Date -Format yyyy-MM-dd | |
# Establish script path for log output | |
$LogPath = "$ScriptPath\Logs" | |
$LogFile = "$LogPath\ServiceAccounts_$DateFormat.txt" | |
$CSVFile = "$LogPath\ServiceAccounts_$DateFormat.csv" | |
$Results = @() | |
#endregion | |
} | |
Process | |
{ | |
# Create the logs directory if it doesn't exist | |
if(-not (Test-Path "$ScriptPath\Logs")) | |
{ | |
$LogsDir = New-Item -Path "$ScriptPath\Logs" -ItemType Directory | |
} | |
# Loop through all computers | |
foreach($C in $ComputerName) | |
{ | |
Write-Tee "[=] Server: $C" | |
# Check the availability of the server and continue | |
if(Test-Connection -ComputerName $C -Count 1 -ErrorAction 0) | |
{ | |
# Check all services | |
$Lang = "service accounts" | |
Write-Tee "[i] Checking for $Lang" | |
# Attempt a WMI connection and collect the services data | |
try | |
{ | |
$Services = Get-WmiObject Win32_Service -ComputerName $C | | |
?{ $_.StartName -ne "LocalSystem" -and $_.StartName -notlike "NT *" -and $_.StartName.Length -gt 1 } | | |
Select @{Name="Server"; Expression = {$_.SystemName}}, | |
Name, StartName, StartMode, State, | |
@{Name="TaskPath"; Expression = {"N\A"}}, | |
@{Name="Type"; Expression = {"Service"}} | |
} catch { Get-Catch } | |
# If WMI didn't work and the version of PowerShell is at least 3 use CIM | |
if(!$Services -and $PSVersionTable.PSVersion.Major -ge 3) | |
{ | |
try | |
{ | |
$Services = Get-CIMInstance Win32_Service -ComputerName $C | | |
?{ $_.StartName -ne "LocalSystem" -and $_.StartName -notlike "NT *" -and $_.StartName.Length -gt 1 } | | |
Select @{Name="Server"; Expression = {$_.SystemName}}, | |
Name, StartName, StartMode, State, | |
@{Name="TaskPath"; Expression = {"N\A"}}, | |
@{Name="Type"; Expression = {"Service"}} | |
} catch { Get-Catch } | |
} | |
# Generate the output and results based on the status of services collected | |
if(!$Services) | |
{ | |
Write-Tee "[i] No $Lang found for $C" | |
} | |
else | |
{ | |
Write-Tee "[r] $($Services.Count) $Lang found for $C" | |
$Services | %{ Write-Tee "[+] [$($_.StartName)] $($_.Name)" } | |
$Results += $Services | |
} | |
# Check all scheduled tasks | |
$Lang = "scheduled tasks" | |
Write-Tee "[i] Checking for $Lang" | |
# If at least Server 2012 use Get-ScheduledTask to get task data otherwise use schtasks | |
if($OSVersion -ge 6.2) | |
{ | |
try | |
{ | |
# Establish a CIMSession with the computer for use with the Get-Scheduled task cmdlet | |
$Cim = New-CimSession $C | |
$Tasks = Get-ScheduledTask -CimSession $Cim | | |
?{ | |
$_.TaskPath -notmatch "Microsoft" -and | |
$_.TaskName -notmatch "Optimize Start Menu Cache" -and | |
$_.TaskName -notmatch "User_Feed_Synchronization" -and | |
$_.Principal.UserId.Length -gt 1 | |
} | Select @{Name="Server"; Expression = {$C}}, | |
@{Name="Name"; Expression = {$_.TaskName}}, | |
@{Name="StartName"; Expression = {$_.Principal.UserId}}, | |
@{Name="StartMode"; Expression = {$_.Principal.RunLevel}}, | |
State, TaskPath, @{Name="Type"; Expression = {"Task"}} | |
} catch { Get-Catch } | |
} | |
else | |
{ | |
try | |
{ | |
# Use schtasks to collect the task data on 2008 R2 and earlier | |
$Tasks = schtasks /query /s $C /V /FO CSV | ConvertFrom-Csv | | |
?{ | |
$_.TaskName -notmatch "TaskName" -and | |
$_.TaskName -notmatch "\\Microsoft\\" -and | |
$_."Run As User" -ne "SYSTEM" -and | |
($_."Run As User").Length -gt 1 -and | |
$_.TaskName -notmatch "User_Feed_Synchronization*" -and | |
$_.TaskName -notlike "GoogleUpdate" | |
} | Select @{Name="Server"; Expression = {$_.HostName}}, | |
@{Name="Name"; Expression = {Split-Path $_.TaskName -Leaf}}, | |
@{Name="StartName"; Expression = {$_."Run As User"}}, | |
@{Name="StartMode"; Expression = {$_."Scheduled Task State"}}, | |
@{Name="State"; Expression = {$_.Status}}, | |
@{Name="TaskPath"; Expression = {$_.TaskName}}, | |
@{Name="Type"; Expression = {"Task"}} | |
} catch { Get-Catch } | |
} | |
# Generate the output and results based on the status of tasks collected | |
if(!$Tasks) | |
{ | |
Write-Tee "[i] No $Lang found for $C" | |
} | |
else | |
{ | |
Write-Tee "[r] $($Tasks.Count) $Lang found for $C" | |
$Tasks | %{ Write-Tee "[+] [$($_.StartName)] $($_.Name)" } | |
$Results += $Tasks | |
} | |
} else { Write-Tee "[!] Unable to connect to $C" } | |
} #foreach($C in $ComputerName) | |
# Export to CSV if enabled and ?{$_} to support older versions of PowerShell | |
if($CSV -and $Results){ $Results | ?{$_} | Export-Csv -Path $CSVFile -NoTypeInformation } | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment