# Windows Service and Process Enumeration

> Enumerate Windows services and processes to identify running applications, privileges, and potential attack vectors using native tools and commands.

- **URL:** https://hackindex.io/platforms/windows/enumeration/windows-service-and-process-enumeration
- **Path:** Windows > Enumeration
- **Up:** [Enumeration](https://hackindex.io/platforms/windows/enumeration.md)
- **Published:** 2026-04-04
- **Updated:** 2026-07-14

Services and processes reveal what is running on the target, under which identity, and with what permissions. Misconfigured services are among the most common privilege escalation paths on Windows. Process enumeration tells you what security tools are active and which user contexts are available for token theft. Look for:

- Processes running as SYSTEM with user-writable binary paths
- Security tool process names indicating active defenses
- Processes owned by domain service accounts (targets for token impersonation with SeImpersonatePrivilege)
- Third-party processes with unusual binary paths (software outside standard hardening baselines)

Note that some EDR products run as kernel drivers and do not appear in tasklist output even when fully active.

## Running processes

**Process enumeration**

```powershell
# All processes
tasklist /v
Get-Process

# Processes with owner
Get-Process -IncludeUserName | Select-Object Name, Id, UserName, Path | Sort-Object UserName

# Processes with service associations
tasklist /svc

# Check for security tools
tasklist | findstr /i "defender crowdstrike sentinel cylance carbon cbdefense tanium symantec mcafee sophos"

# Find processes running as SYSTEM or admin accounts
Get-Process -IncludeUserName | Where-Object {$_.UserName -match 'SYSTEM|Administrator|Domain'} | Select-Object Name, Id, UserName
```

## Service enumeration

Enumerate all services with their binary paths, run-as accounts, and start types. Services running as SYSTEM with weak permissions are direct escalation paths. The PathName field is your primary target. Paths pointing into user-writable directories like AppData or temp folders are immediately actionable. The StartName field shows the execution context. LocalSystem grants full SYSTEM privileges. NT AUTHORITY\NetworkService and NT AUTHORITY\LocalService carry restricted token privileges but remain useful for token abuse. Non-standard accounts such as svc_backup or svc_sql frequently have credentials stored in LSA secrets or hardcoded in application configs. Stopped services are not irrelevant. A service set for manual start can be reconfigured and triggered if you hold sufficient permissions on the service object. Automatic-start services currently in a stopped state may indicate recent crashes worth investigating further.

**Service enumeration**

```powershell
# All services with details
sc query type= all state= all
Get-Service | Select-Object Name, DisplayName, Status, StartType

# Services with binary paths and run-as accounts
Get-WmiObject Win32_Service | Select-Object Name, DisplayName, State, StartMode, PathName, StartName | Sort-Object StartName

# Services running as SYSTEM
Get-WmiObject Win32_Service | Where-Object {$_.StartName -eq 'LocalSystem'} | Select-Object Name, PathName

# Services running as non-standard accounts (interesting for cred hunting)
Get-WmiObject Win32_Service | Where-Object {$_.StartName -notmatch 'LocalSystem|NetworkService|LocalService|NT AUTHORITY'} | Select-Object Name, PathName, StartName
```

## Service permission checking

Services with overly permissive ACLs allow low-privilege users to modify the binary path and escalate to SYSTEM. Check permissions on both the service itself and its binary. In accesschk output, look for SERVICE_ALL_ACCESS, SERVICE_CHANGE_CONFIG, or SERVICE_WRITE_DAC granted to Authenticated Users or the current user. Any of those rights means you can reconfigure the binary path directly. The binary path check catches misconfigurations that survive a clean service ACL. A locked-down service pointing to a writable binary is still fully exploitable. Unquoted paths with spaces allow binary planting without touching the service object at all. Windows resolves each space-delimited segment of an unquoted path as a candidate executable in order. A service path inside Program Files that contains a space but no quotes causes Windows to attempt shorter executable names. It tries each space-delimited prefix before reaching the real binary. If you can write to any intermediate directory in that path, you can plant a file that runs instead. This pattern is common with third-party software installed outside standard directories. The PowerShell ACL check in the terminal block uses regex matching on identity reference strings. It may miss accounts on non-English Windows installs where group names appear in the local language. Run whoami /groups and cross-reference manually if the output looks unexpectedly empty.

**Check service and binary permissions**

```powershell
# accesschk: check service permissions for current user
accesschk.exe /accepteula -uwcqv $USER *
accesschk.exe /accepteula -uwcqv "Authenticated Users" *
accesschk.exe /accepteula -uwcqv "Everyone" *

# Check binary file permissions for all services
Get-WmiObject Win32_Service | ForEach-Object {
    $path = $_.PathName -replace '"',''
    $path = ($path -split ' ')[0]
    if (Test-Path $path) {
        $acl = Get-Acl $path
        $acl.Access | Where-Object {
            $_.IdentityReference -match 'Users|Everyone|Authenticated' -and
            $_.FileSystemRights -match 'Write|FullControl|Modify'
        } | ForEach-Object {
            Write-Host "Writable binary: $path ($($_.IdentityReference))"
        }
    }
}

# Unquoted service paths (spaces without quotes)
Get-WmiObject Win32_Service | Where-Object {$_.PathName -notmatch '"' -and $_.PathName -match ' '} | Select-Object Name, PathName
```

Writable service binaries lead to [Service Binary Hijacking](https://hackindex.io/platforms/windows/privilege-escalation/service-binary-hijacking). Unquoted paths lead to [Unquoted Service Path Privilege Escalation](https://hackindex.io/platforms/windows/privilege-escalation/unquoted-service-paths). Weak service permissions lead to [Weak Service Permissions Privilege Escalation](https://hackindex.io/platforms/windows/privilege-escalation/weak-service-permissions-privilege-escalation). Prioritize misconfigurations that require no file writes to disk. Weak service permissions and unquoted paths are often the cleanest paths to SYSTEM. Binary replacement requires writing to disk, which may trigger AV or EDR before the service restarts.

## Scheduled tasks

Scheduled tasks are frequently overlooked during service enumeration but follow the same logic. Filter out Microsoft-owned tasks first and focus on third-party entries. Third-party tasks often execute custom scripts or binaries under elevated accounts. Check the RunAs account and the action path together. A task running as SYSTEM that calls a user-writable script is directly exploitable. Look for action paths inside user profile directories, shared folders, or temp locations. The Principal element shows the privilege level but analysts often miss the actual script path being called. The LastRunTime field tells you whether a task is actively used. A task that has never run may still fire on the next trigger cycle. If the action path is writable, replace the target script before the next scheduled run. Tasks with no LastRunTime and a future trigger are particularly worth targeting in active engagements.

**Scheduled task enumeration**

```powershell
# All non-Microsoft tasks
Get-ScheduledTask | Where-Object {$_.TaskPath -notlike "\Microsoft*"} | Select-Object TaskName, TaskPath, State

# Task details including action and run-as account
Get-ScheduledTask | Where-Object {$_.TaskPath -notlike "\Microsoft*"} | ForEach-Object {
    $task = $_
    $info = Get-ScheduledTaskInfo -TaskName $task.TaskName -TaskPath $task.TaskPath -ErrorAction SilentlyContinue
    [PSCustomObject]@{
        Name = $task.TaskName
        RunAs = $task.Principal.UserId
        Action = ($task.Actions | Select-Object -First 1).Execute
        LastRun = $info.LastRunTime
    }
}

# Check permissions on task scripts
schtasks /query /fo LIST /v | findstr /i "task to run run as"
```
