Services
A Windows service is a background process managed by the Service Control Manager. Services can be controlled using services snap-in (services.msc), PowerShell, or sc.exe (command-line tool). They typically run under specific built-in accounts but can be also run under custom user accounts, such as local or domain users:
LocalSystem: High privileges (includes
SYSTEMandAdministratorSIDs)Network Service: Limited privileges with network access
Local Service: Limited privileges without network access
Binary Hijacking
For automated Service Binary Hijacking see
PowerUp.
Every Windows service has an associated binary that runs when the service starts, and if its permissions are misconfigured, a low-privileged user may be able to replace it with a malicious file. For example, a developer might install a service but fail to properly restrict access, allowing any user to modify the binary. An attacker could exploit this by replacing the binary with their own payload, and then triggering its execution by restarting the service or rebooting the system—causing the malicious code to run with elevated privileges such as LocalSystem.
To list Windows services and their binaries we can use the GUI app
services.msc, or theGet-ServiceandGet-CimInstancecmdlets.
# Filter running services and their executable paths
> Get-CimInstance -ClassName win32_service | Select Name, State, PathName | Where-Object { $_.State -eq "Running" }
Name State PathName
---- ----- --------
Apache2.4 Running "C:\xampp\apache\bin\httpd.exe" -k runservice
Appinfo Running C:\Windows\system32\svchost.exe -k netsvcs -p
AppXSvc Running C:\Windows\system32\svchost.exe -k wsappx -p
mysql Running C:\xampp\mysql\bin\mysqld.exe --defaults-file=c:\xampp\mysql\bin\my.ini mysqlNetwork logons (e.g., WinRM, bind shells) may fail when querying services as a non-admin user, while interactive logins (e.g., RDP) work without permission issues.
From the list above, the binaries located in the C:\xampp instead of the C:\Windows\System32 directory (apache2.4 and mysql) stand out because this means that these services are user-installed and are, therefore, susceptible to permission misconfigurations. We can enumerate their permissions using icacls or Get-ACL .
F
Full Access
M
Modify Access
RX
Read & Execute
R
Read-only
W
Write-ony
We will create a malicious binary to replace the original mysqld.exe.
We can stop and then start the service:
Or restart it in one step (sometimes one approach might work while the other not):
If the user does not have to restart the service but has the SeShutDownPrivilege assigned and the StartMode of the service is set to Auto, we can just reboot the system.
To restore the original state of the service, we have to delete our binary
mysqld.exe, restore the backed up original binary, and restart the system.
We can also get a reverse shell by replacing the binary with the following.
Scheduled Tasks
Windows uses Task Scheduler to run automated jobs, known as Scheduled Tasks, based on defined triggers (e.g., at startup, login, or a specific time). Each task has one or more actions—scripts or programs to execute—configured under its properties. For privilege escalation, the focus is on three key details:
User context: Does the task run as
SYSTEMor anadministrator?Triggers: When does it run? Is the condition re-usable within the testing window?
Actions: What program or script runs?
Scheduled tasks can also be leveraged to get a reverse shell as SYSTEM:
DLL Hijacking
If binary service hijacking isn't possible due to permission restrictions, DLL hijacking, a more stealthier method, can be used. DLLs are essential components that provide shared functionality to Windows programs. By replacing a DLL that a service depends on, malicious code can be injected while maintaining the service's functionality.
DLLs are called Shared Objects on Unix.
When a program needs a DLL, Windows follows a predefined search order to locate it. To improve security, Microsoft introduced safe DLL search mode, which prioritizes system directories to prevent unauthorized DLL loading. The standard search order is:
However, if a program looks for a missing DLL (due to installation issues or updates), a malicious DLL can be placed with the same name in a directory higher in the search order, a technique known as DLL search order hijacking.
Filezilla 3.63.1 has a DLL hijacking vulnerability related to the TextShaping.dll file. We first need to check if we have write access to the DLL's location.
The typical process of checking which DLLs are used by an application is via the Process Monitor tool, aka as procmon. Once we have a list of DLLs used by the service binary, we can check their permissions and if they can be replaced with a malicious DLL.
To start the Process Monitor we need elevated privileges. If we don't, we can copy the service binary to a local machine instead.

After filtering the results, we can click Clear (red bin icon) and start the process we are interested in. Since we are interested specifically in the TextShaping.dll we can create another filter targeting that.

Based on the above screenshot, the binary tries to load the TextShaping.dll from C:\Filezilla\Filezilla FTP Client\ and it can't find it. It then proceeds to search and find it from C:\Windows\System32\.
Each DLL can have an optional entry point function named DllMain, which is executed when processes or threads attach the DLL. This function generally contains four cases named:
DLL_PROCESS_ATTACHDLL_THREAD_ATTACHDLL_THREAD_DETACHDLL_PROCESS_DETACH
These cases handle situations when the DLL is loaded or unloaded by a process or thread. They are commonly used to perform initialization tasks for the DLL or tasks related to exiting the DLL. If a DLL doesn't have a DllMain entry point function, it only provides resources. We are interested in the DLL_PROCESS_ATTACH section of the code, since this is used when a process is loading the DLL.
In order for the DLL hijacking to trigger the FileZilla FTP Client needs to be started, however, it is important to keep in mind that the privileges the DLL will run with depend on the privileges used to start the application. If we were to start the FTP client as a low-privileged user, then we would not have the required privileges for our payload to work, i.e., to add a new user to the system and place them in the Administrators group.
Some binaries need to be started as a service in order to function properly:
We can also try changing directly the service's configuration:
Unquoted Service Paths
For automated enumeration and exploitation of this vector, see here.
Each Windows service maps to an executable file.
When a service starts, a process is created via the
CreateProcessfunction.The first parameter of this function,
IpApplicationName, specifies the name and, optionally, the executable path. If the latter is an unquoted string that contains spaces, it can be used as a privilege escalation vector due to how Windows interprets the path.
For example, C:\Program Files\My Program\My Service\service.exe will be interpreted as:
We can exploit this by creating a malicious executable in any of the paths before the original one. This will result in the former executing with the same privileges that the service starts with, typically, LocalSystem.
Enumerate the service:
Check service's details, such as the Run As User: field:
Last updated
Was this helpful?