Find User-Based Service Accounts with PowerShell and Command Line

For the most part, Windows Server services run under generic system based accounts, such as LocalSystem or NT AUTHORITY\LocalService. But occasionally, a service needs to be run under a “real” user account, either domain or machine-based. Too often I’ve seen these running under an administrator account. In any event, you should know where these types of service accounts are being used.

Find User-Based Service Accounts with PowerShell

The first thing you might want to do is find out what accounts are currently being used. PowerShell is the easiest tool. We can use WMI to query all instances of the Win32_Service class and look at the StartName property. One approach might be to use Group-Object.

​PS C:\> get-wmiobject win32_service -comp jdhit-dc01 | Group Startname -NoElement | Sort Count
Count Name
----- ----
    1 administrator@jdhitsol...
    1 JDHITSOLUTIONS\Adminis...
   10 NT AUTHORITY\NetworkSe...
   14 NT AUTHORITY\LocalService
   79 LocalSystem

This gives me a nice distribution breakdown, but I can see there are a few services using a user account. If I know in advance what account to search for, I could run a PowerShell command like this:

​PS C:\> get-wmiobject win32_service -comp jdhit-dc01 -filter "Startname Like '%Administrator%'" | select name,startname
name                                    startname
----                                    ---------
MSSQL$MICROSOFT##SSEE                   [email protected]
RSEEService                             JDHITSOLUTIONS\Administrator

A better approach would be to filter out all the system accounts. This is a little tricky with WMI filtering, but here’s something that should do the trick.

​PS C:\> get-wmiobject win32_service -comp jdhit-dc01 -filter "Startname Like '[^NT Authority|LocalSystem]%' OR Startname Like '%@%'" | select name,startname
name                                    startname
----                                    ---------
MSSQL$MICROSOFT##SSEE                   [email protected]
RSEEService                             JDHITSOLUTIONS\Administrator

In my testing, I’ve found I need the compound filter to pick up accounts using the UPN format. But now, given a list of computernames, I could build a report like this.

​PS S:\> get-wmiobject win32_service -comp (get-content computers.txt) -filter "Startname Like '[^NT Authority|LocalSystem]%' OR Startname Like '%@%'" | select systemname,name,startname | export-csv svcaccounts.csv –NoTypeInformation

This will create a simple CSV file which I can open in Excel.

Find User-Based Service Accounts with the Command Line

If you prefer your WMI in a CLI flavor, you can also use WMIC from a a CMD prompt.

​C:\>wmic service where 'startname like "[^NT Authority|LocalSystem]%"' Get Name,
Displayname,StartName
DisplayName                   Name                                  StartName
SQL Server (SQLExpress)       MSSQL$SQLEXPRESS                      .\sql
Veeam Backup Service          Veeam Backup and Replication Service  .\Jeff
Veeam Backup Catalog Service  Veeam Backup Catalog Data Service     .\Jeff

WMIC can be a bit tricky, so if you are interested in using it, you might want to check out my articles on the subject. [Command Line WMI Part 1; Command Line WMI Part 2; Command Line WMI Part 3]
Now, if PowerShell isn’t an option for you and you find WMIC awkward, you could turn to the command line tool SC.EXE to retrieve the same information. If you suspect a service, it is pretty easy to check.

​C:\>sc qc mssql$sqlexpress
[SC] QueryServiceConfig SUCCESS
SERVICE_NAME: mssql$sqlexpress
        TYPE               : 10  WIN32_OWN_PROCESS
        START_TYPE         : 2   AUTO_START  (DELAYED)
        ERROR_CONTROL      : 1   NORMAL
        BINARY_PATH_NAME   : "c:\Program Files\Microsoft SQL Server\MSSQL10.SQLEXPRESS\MSSQL\Binn\sqlservr.exe" -sSQLEXPRESS
        LOAD_ORDER_GROUP   : P@ssw0rd
        TAG                : 0
        DISPLAY_NAME       : SQL Server (SQLExpress)
        DEPENDENCIES       :
        SERVICE_START_NAME : .\sql

Scripting this to check all services is a bit more tedious, and after more time than I would have wanted, I came up with a batch file you could use. Don’t expect a speedy result like PowerShell, as the script has to get a list of all services and then get the configuration for each service and check the service start name.

​@echo off
::GetServiceAccount.bat
::Jeffery Hicks
::  http://jdhitsolutions.com/blog
::  http://twitter.com/jeffhicks
::USAGE GetServiceAccount [computername]
::You must run this with an account that has admin rights on any remote computer
if %1$==$ (
 set zcomp=%Computername%
) else ( set zcomp=%1  )
echo Finding non system service accounts on %zcomp%
rem get a list of service names
sc \\%zcomp% query type= service state= all | findstr /i "Service_Name" > %temp%\~zlist.qqq
for /f "tokens=2* delims=: " %%i in (%temp%\~zlist.qqq) Do if %%j$==$ (Call :Check %zcomp% %%i) else ( Call :Check %zcomp% "%%i %%j")
goto :Exit
:Check
rem echo %2
rem create a temp file
sc \\%1 qc %2 | findstr /i "Name" > %temp%\~foo.qqq
rem define a counter
set zcount=0
rem test for service account name
findstr /i "service_start_name" %temp%\~foo.qqq | findstr /i /r "\<LocalSystem" > NUL
if errorlevel 1 set /a zcount+=1
findstr /i "service_start_name" %temp%\~foo.qqq | findstr /i /r "\ NUL
if errorlevel 1 set /a zcount+=1
rem If neither type of entry was found then display the temp file
if %zcount% equ 2 type %temp%\~foo.qqq
:Exit
set zcomp=
set zcount=
rem delete temp file if it still exists
if Exist %temp%\~foo.qqq del %temp%\~foo.qqq
if Exist %temp%\~zlist.qqq del %temp%\~zlist.qqq

But it works:

​C:\>c:\scripts\GetServiceAccount.bat JDHIT-DC01
Finding non system service accounts on JDHIT-DC01
SERVICE_NAME: MSSQL$MICROSOFT##SSEE
        BINARY_PATH_NAME   : C:\WINDOWS\SYSMSI\SSEE\MSSQL.2005\MSSQL\Binn\sqlser
vr.exe -sMICROSOFT##SSEE
        DISPLAY_NAME       : Windows Internal Database (MICROSOFT##SSEE)
        SERVICE_START_NAME : [email protected]
SERVICE_NAME: RSEEService
        BINARY_PATH_NAME   : "C:\Program Files\SAPIEN Technologies, Inc\RSEE Ser
vice\rexecService.exe"
        DISPLAY_NAME       : Remote Script Execution
        SERVICE_START_NAME : JDHITSOLUTIONS\Administrator
C:\>

Conclusion

Personally, I’ll stick to PowerShell but I wanted to leave you with some options. In any event, now you should be able to identify what accounts your services are running under, and identify potential problems before they become major headaches. If you want to try the batch file, you can download it here.