TL;DR
- Vendors are notorious for including and/or leaving behind Registry artifacts that could potentially be abused by attackers for lateral movement, evasion, bypass, and persistence.
- CLSIDs subkeys (LocalServer32 and InprocServer32) can be enumerated to discover abandoned binary references.
- Interestingly, CLSIDs can be called (‘invoked’) with this command:
rundll32.exe -sta {CLSID}
- Defensive recommendations – clean up artifacts after removal (e.g. unregister), monitor for suspicious events (e.g. rundll32.exe usage), and implement strong Application Whitelisting (AWL) policies/rules.
Background
Previously, I blogged about a DCOM lateral movement technique that took advantage of a missing file that was referenced in a registry Class Identifier (CLSID) subkey-value on Windows 2008/2012 hosts. After seeing the impact of that technique, the entire notion of COM (Component Object Model) & key-value path hijacking became even more fascinating to me. As such, I decided to revisit CSLIDs, LocalServer32, and InprocServer32 to (hopefully) uncover even more interesting findings.
In this post, we will discuss:
- The purpose of CLSIDs, LocalServer32, and InprocServer32
- A slightly improved method for enumerating LocalServer32 and InprocServer32 keys and missing key references
- The DCOM lateral movement method
- Rundll32 and CLSID abuse
- Several defensive recommendations
Let’s dive in…
A Quick Primer on CLSID, LocalServer32, & InprocServer32
Most COM classes are registered with the operating system and are identified by a GUID that represents the Class Identifier (CLSID) within the registry (usually under HKLM\Software\Classes\CLSID or HKCU\Software\Classes\CLSID). Behind the implementation of a COM class is the ‘server’ (some binary) that is referenced within registry keys under the CLSID. The LocalServer32 key represents a path to an executable (exe) implementation, and the InprocServer32 key represents a path to a dynamic link library (DLL) implementation.
In the registry, CLSID structures look something like these:
LocalServer32
[Click image to zoom in]
InprocServer32
[Click image to zoom in]
*Reference: New lateral movement techniques abuse DCOM technology
by Philip Tsukerman (@PhilipTsukerman) of CyberReason
Enumerating LocalServer32/InprocServer32 Keys and Locating Abandoned Binary References
In the Windows O/S, there are many COM classes, and the number of those that have missing references to binary paths in the data fields of LocalServer32/InprocServer32 depends on a few factors such as:
- The operating system version, family, and features
- 3rd party software (as installed/after uninstall)
- (Prior) DLL/COM registration
To locate these missing paths, consider these general steps:
- Enumerate all LocalServer32 and InprocServer32 values to abstract reference binary (path)
- Normalize binary path to remove arguments and switches (if applicable)
- Validate binary path existence and locate missing files
LocalServer32
Let’s enumerate all LocalServer32 key values with the following PowerShell snippet:
$inproc = gwmi Win32_COMSetting | ?{ $_.LocalServer32 -ne $null }
$inproc | ForEach {$_.LocalServer32} > values.txt
In this case (on a Win2k12 R2 machine), we redirect the output to file (values.txt) for editing command arguments and switches.
After normalizing the file, we can locate potentially missing values with the following snippet:
$paths = gc .\values.txt
foreach ($p in $paths){$p;cmd /c dir $p > $null}
In our test case, we can see the following results with something that may look familiar from the previous post:
InprocServer32
You will likely find many more Registry CLSID classes with InprocServer32 keys. From the System32 directory, we can run the following snippet without having to worry about normalizing enumerated results (too much):
$inproc = gwmi Win32_COMSetting | ?{ $_.InprocServer32 -ne $null }
$paths = $inproc | ForEach {$_.InprocServer32}
foreach ($p in $paths){$p;cmd /c dir $p > $null}
*Note: You may want to grab a cup of coffee while this is running – it may take a few minutes. Also, consider redirecting this output to file for easier analysis.
On one of my Win10 virtual machines, this missing reference was somewhat interesting:
It is not surprising to see interesting artifacts left behind by (trusted) vendor software in addition to Windows gaps. These abandoned registry elements do not necessarily indicate that a vulnerability is present (e.g. due to ACLs on a directory structure) in an unprivileged user context, but these artifacts may create an opportunity for an attacker to “blend in” and influence the registry structure in other ways (e.g. COM Hijacks).
Revisiting the DCOM Lateral Movement Technique
In Windows 2008 and Windows 2012 baseline installations, the COM CLSID structure for C947D50F-378E-4FF6-8835-FCB50305244D has a LocalServer32 subkey that points to %SystemRoot%\system32\mobsync.exe.
Following the enumeration methodology above, the file path is enumerated and the referenced binary is clearly not present at the file location. Since this COM object can be instantiated remotely (when not locked down), it is clear candidate to abuse for DCOM lateral movement.
More information can be found in this blog post – Abusing DCOM For Yet Another Lateral Movement Technique.
Abusing Registry COM CSLIDs with Rundll32
If you follow me on Twitter, you may already know about this technique :-). However, this blog is a better place to document it. While enumerating the LocalServer32 keys on a Windows 10 machine, I came across this very interesting CLSID and LocalServer32 key-value:
%SystemRoot%\system32\rundll32.exe /sta {fcc2867c-69ea-4d85-8058-7c214e611c97}
The -sta (/sta) switch refers to “single-threaded apartment” which is a part of the COM Threading Architecture. Beyond Microsoft documentation about COM apartments, I could not find much information about the -sta switch in rundll32.exe. Interestingly, powershell.exe has a -sta switch to start powershell with a single threaded apartment (by default after version 2 anyway). When called with the respective CLSID (or ProgID if available), this switch in rundll32.exe loads (‘invokes’) the reference binary via LocalServer32 or InprocServer32. My background understanding of this is still naive, but it has some interesting implications for abusing COM.
Evasive DLL Loading
As alluded to in the enumeration section, I discovered registry artifacts from VMware Workstation that were left behind after uninstalling the software from the machine. Interestingly, the following CLSID and directory structures were still in place:
The folder structure also remained without the software binaries and dependencies. The following ACL entries were effective on this folder:
(Un)fortunately, an unprivileged user lacks the ability to write to this directory. However, we can still demonstrate a privileged user’s attempt to “blend in” by copying a ‘malicious’ DLL into the directory as ‘vmnetbridge.dll’ to influence InprocServer32 key loading:
Let’s use the following command to load our DLL payload with the corresponding CLSID:
rundll32.exe -sta {3d09c1ca-2bcc-40b7-b9bb-3f3ec143a87b}
Granted, this example loads under a privileged context, but the implications *could* become very interesting if a normal user can influence a path element of ‘abandoned’ registry CLSIDs.
In general, this also makes for a viable persistence mechanism via Run key or Scheduled Task.
AWL Bypass Via Traditional COM Hijacking
With a legitimate CLSID reference and registered Program ID (ProgID), we can simply hijack a registered COM structure under the context of an unprivileged user. In this example, let’s load Casey Smith’s (@subTee) “scripting.dictionary” COM Hijack reg file that calls a remote COM script. This sets us up for a “squiblydoo” AppLocker bypass (using default rules):
For clarity, this hijack works because the CLSID values in HKCU take precedent over CLSID values in HKLM (*Thanks to @KyleHanslovan for the reminder!).
Now, let’s run the following rundll32.exe command to call the influential COM CLSID and execute the Jscript code:
rundll32.exe -sta {00000001-0000-0000-0000-0000FEEDACDC}
Quick Update:
After chatting with @PhilipTsukerman about other ways to bootstrap and load COM classes, it is worth noting that the command can be called by ProgID if there is a corresponding key. In this case, “scripting.dictionary” is hijacked, so this works as well:
rundll32.exe -sta "scripting.dictionary"
Defensive Considerations
- Vendors should remove (e.g. unregister) COM registry artifacts (and disk artifacts) when utility software is uninstalled. Additionally, vendors should not create CLSID binary path registry key-values that point to non-existent binaries.
- Net defenders should monitor for interesting host activity, especially for rundll32.exe usage. Take note the ‘sta’ switch can be successfuly called with a suffix such as ‘stagggg’ or ‘stagggggggggggggggggg’ along with the CLSID.
- Organizations should implement strong Application Whitelisting (AWL) policies and move beyond default rules.
Conclusion
Thank you for taking the time to read this post! I hope to have a follow up post on related subject matter as more depth is explored, so check back soon!
~ bohops
2 thoughts on “Abusing the COM Registry Structure: CLSID, LocalServer32, & InprocServer32”
Comments are closed.