PoshCode Logo PowerShell Code Repository

Get-ServiceAccounts (modification of post by gesizem view diff)
diff | embed code: <script type="text/javascript" src="http://PoshCode.org/embed/503"></script>download | new post

Script will help discover any service accounts that are currently being used. I have been using this script for about a month in production. While your mileage may vary this script is strictly read only, thus -confirm, and -whatif are not supported.

V.1 Initial Build
V.1.1 Optimized GWMI query
V.1.2 Added logic to record the cause of a failed query

  1. #requires -pssnapin PSCX
  2. #Author:     Glenn Sizemore glnsize@get-admin.com
  3. #Purpose:    Scan a remote system for any services running under a non standard account.
  4. #            Standard accounts would be considered, NT AUTHORITY\NetworkService,
  5. #            NT AUTHORITY\LocalService, LocalSystem, or .\ASPNET
  6. #            
  7. #Usage:      PS > Get-ServiceAccounts [-Target <string>] [-Path <string>] [-verbose] [-Credential <PSCredential Object> ]
  8. #            
  9. #            -Target(optional)  
  10. #                  can be either a string or an array of strings.
  11. #            -Path(optional)    
  12. #                 Path to an item containing a list of Targets
  13. #            -Verbose(optional)
  14. #                 turns on verbose logging to the console
  15. #            -Credential(optional)
  16. #                  should only be used with V2, uses alternate credentials when
  17. #                querying target for services.
  18. #
  19. #Returns:    PSCustom Object
  20. #
  21. #Example:    Get-ServiceAccounts -Target "host1","host2","host3" -Path "C:\temp\otherhosts.txt" -verbose
  22. #            
  23. #            this command will combined the targets: host1, host2, and host3 with all targets located in
  24. #            the file otherhost.txt, and scan all of them for unique service accounts.
  25. #
  26.  
  27. param($target,
  28. [string]$Path,
  29. [switch]$verbose,
  30. [System.Management.Automation.PSCredential]$credential = ($null)
  31. )
  32. begin
  33. {
  34.     # Create an empty object to hold all service accounts found.
  35.     $SvcAccounts = @()
  36.  
  37.     #Save the current $ErrorActionPreference so we can restore it.
  38.     $ErrActionSave = $ErrorActionPreference
  39.     $Verbosesave = $VerbosePreference
  40.     $warningSave = $WarningPreference
  41.  
  42.     #If a PSCredential is supplied then wmi query will be ran under that account.
  43.     if ($credential)
  44.     {
  45.         Write-Host "there is a known bug using -credential in V1..."
  46.         $gwmiquery = {Get-WmiObject -Class Win32_Service -ComputerName $computer -Credential $credential `
  47.             -property name, startname, caption, StartMode `
  48.             -filter 'NOT Startname LIKE "%NT AUTHORITY%" AND NOT Startname LIKE "LocalSystem" AND NOT Startname LIKE "ASPNET"'}
  49.     }
  50.     else
  51.     {
  52.         $gwmiquery = {Get-WmiObject -Class Win32_Service -ComputerName $computer -property name, startname, caption, StartMode `
  53.             -filter 'NOT Startname LIKE "%NT AUTHORITY%" AND NOT Startname LIKE "LocalSystem" AND NOT Startname LIKE "ASPNET"'}
  54.     }
  55.  
  56.     if ($Verbose) {$VerbosePreference = "Continue"; $WarningPreference = "Continue"}
  57.  
  58.     #Workhorse...
  59.     function ProcessTarget ($computer)
  60.     {
  61.         $obj = @()
  62.  
  63.         #Set ErrorAction to silent... we'll handle the error's ourselves.
  64.         $ErrorActionPreference = "SilentlyContinue"
  65.  
  66.         Write-Verbose "querying $computer ..."
  67.  
  68.         #call the Query from above.
  69.         $services = &$gwmiquery
  70.  
  71.         #set erroraction back there sould be no error's from here on out.
  72.         $ErrorActionPreference = $ErrActionSave
  73.  
  74.         Write-Verbose " $($services.count) services located on $computer using "
  75.         foreach ($service in $Services)
  76.         {
  77.  
  78.             # If there was an error while attempting the gwmi call, there will be only one error.
  79.             # We check that error to help annotate why we were unsuccessful.
  80.             switch -regex ($Error[0].Exception)
  81.             {
  82.                 "The RPC server is unavailable"
  83.                 {
  84.                     Write-warning "RPC Unavailable on $computer"
  85.                     $obj += "" | Select @{e={$computer};n='Target'},@{e={"RPC_Unavalable"};n='SvcName'}
  86.                     continue
  87.                 }
  88.                 #vista
  89.                 "Access denied"
  90.                 {
  91.                     Write-warning "Access Denied on $computer"
  92.                     $obj += "" | Select @{e={$computer};n='Target'},@{e={"Access_Denied"};n='SvcName'}
  93.                     continue
  94.                 }
  95.                 #XP/Server 2k3
  96.                 "Access is denied"
  97.                 {
  98.                     Write-warning "Access Denied on $computer"
  99.                     $obj += "" | Select @{e={$computer};n='Target'},@{e={"Access_Denied"};n='SvcName'}
  100.                     continue
  101.                 }
  102.                 $null
  103.                 {
  104.                     $obj += "" | Select @{e={$computer};n='Target'},
  105.                     @{e={$service.name };n='SvcName'},
  106.                     @{e={$service.startname };n='SvcAcccount'},
  107.                     @{e={$service.caption };n='SvcDes'},
  108.                     @{e={$service.StartMode };n='StartMode'}
  109.                 }
  110.             }
  111.             $Error.clear()
  112.         }
  113.         return $obj
  114.     }
  115. }
  116. process
  117. {
  118.     $Targets = @()
  119.     if ($Path){$Targets = Get-Content $Path}
  120.     if ($Target){$Targets += $target}
  121.  
  122.     foreach ($computer in $Targets)
  123.     {
  124.         ping-host -HostName $computer -Count 1 -Quiet -Timeout 1| Where-Object { $_.loss -ne 100} | `
  125.         ForEach-Object {$SvcAccounts += ProcessTarget $_.host}
  126.     }
  127.  
  128. }
  129. End
  130. {
  131.     $ErrorActionPreference = $ErrActionSave
  132.     $VerbosePreference = $Verbosesave
  133.     $WarningPreference = $warningSave
  134.     Write-Output $SvcAccounts
  135. }

Submit a correction or amendment below (
click here to make a fresh posting)
After submitting an amendment, you'll be able to view the differences between the old and new posts easily.

Syntax highlighting:


Remember me