Network attacks often contain a lateral movement stage when adversaries move through the target’s network to find the data or asset that they’re ultimately after.
Read about Philip's other research on manipulating Excel4.0 macros.
In the absence of vulnerable machines or an EternalBlue-like exploit, this phase is carried out by leveraging stolen credentials to achieve execution on a remote machine that’s reachable from an initial foothold in the network.
Unlike the initial intrusion, which is commonly carried out by social engineering or exploiting vulnerabilities, attackers abuse legitimate OS features to conduct lateral movement. On Windows machines, lateral movement is usually carried out using variations on a few methods, particularly Remote Service Creation, Remote Task Scheduling and Remote WMI Process Creation. Closely monitoring these features for strange executions could yield some easy victories against threat actors. Even a meticulously planned campaign using various evasion techniques could be detected simply because the attackers have created a remote service in an environment that monitors this kind of actions closely.
Recently, this arsenal of lateral movement techniques was expanded with some new methods (mostly discovered by Matt Nelson of SpecterOps, and a couple by myself with research help from Oren Ofer) that abuse the DCOM (Distributed Component Object Model) functionality of various Windows applications. This article will review the various methods of DCOM lateral movement (including some that are yet undocumented), assess their use cases and forensic artifacts and offer methods to detect and prevent the use of these techniques.
A bit about DCOM
DCOM is an extension of COM (Component Object Model), which allows applications to instantiate and access the properties and methods of COM objects on a remote computer just like objects on the local machine using the DCERPC-based DCOM protocol. Information about the identity, the implementation and the configuration of every COM (and DCOM) object is stored in the registry, and associated with a few important identifiers:
- CLSID - The Class Identifier is a GUID, which acts as a unique identifier for a COM class, and every class registered in Windows is associated with a CLSID (COM objects may be used without registration, but that is beyond the scope of this article). The CLSID key in the registry points to the implementation of the class, using the InProcServer32 subkey in case of a dll-based object, and the LocalServer32 key in case of an exe.
- ProgID - The Programmatic Identifier is an optional identifier, which can be used as a more user-friendly alternative to a CLSID, as it does not have to adhere to the intimidating GUID format of CLSIDs ("System.AppDomainManager", for example, is much easier on the eyes than a GUID). ProgIDs are not guaranteed to be unique, and unlike CLSID, not every class is associated with a ProgID.
- AppID - The Application Identifier is used to specify the configuration of one or more COM objects associated with the same executable. This includes the permissions given to various groups to instantiate and access the associated classes, both locally and remotely
To make a COM object accessible by DCOM, an AppID must be associated with the CLSID of the class and appropriate permissions need to be given to the AppID. A COM object without an associated AppID cannot be directly accessed from a remote machine.
The Win32_DCOMApplication WMI class provides an easy method to enumerate available DCOM applications by AppID
The instantiation of a remote DCOM object behaves as follows:
- The client machine requests an instantiation of an object denoted by a CLSID from a remote machine. If the client uses a ProgID, it is first resolved locally to a CLSID.
- The remote machine checks if there is an AppID associated with the CLSID in question, and verifies the permissions of the client.
- If all goes well, the DCOMLaunch service creates an instance of the requested class, most commonly by running the executable of the LocalServer32 subkey, or by creating a DllHost process to host a dll referenced by the InProcServer32 subkey.
- Communication is established between the client application and the server process. In most cases, the new process is created in the session associated with the DCOM communication.
- The client is then able to access the members and methods of the newly created object.
DETERMING AN APPLICATION WAS STARTED USING DCOM
Excluding locally instantiated InProcServer classes (which are loaded into the calling process) and objects that are hosted by an existing process, Object creation is handled by the DCOMLaunch service. This service is implemented in the rpcss.dll library and can be identified with the "C:\WINDOWS\system32\svchost.exe -k DcomLaunch" command line. As such, new processes started by COM have the DCOMLaunch service as their parent process. Knowing a process was started via COM, it's easy to determine if it is used locally or remotely. To communicate with a local client, a COM object uses the ALPC (Advanced Local Procedure Call) inter-process communication mechanism. Otherwise, it must communicate with the remote client via the DCOM protocol, which is mostly done on high ports, unless explicitly configured otherwise. A remotely used DCOM object can therefore be identified by a combination of a DCOMLaunch parent and a socket listening on a high port. Office applications specifically are started via COM with the "-Embedding" or the "/automation -Embedding" command line options.
DCOM lateral movement methods
The methods below are grouped by the possible effect their execution may have on a system. Most of these have been published before, and some are variations that, to the best of our knowledge, have never been documented.
Arbitrary Command Line Execution
First published by Cybereason here.
This uses the recently infamous Direct Data Exchange inter-process communications of Excel to execute an arbitrary command line.
To perform this technique, first create an instance of the "Excel.Application" object, which is the COM object associated with Excel automation. "xxx.xxx.xxx.xxx", in all future examples, stands for a target address:
This is followed by suppression of alerts and execution:
The Excel process runs the chosen command line and tries to establish a DDE channel with said application. It returns an error code upon failing, but the command is still run.
- Artifacts and Indicators - The executed command is run as a child process of Excel.
- Limitations - The name of the application is limited to 8 characters, which only allows to use executables such as cmd.exe, which are pointed to by the %PATH% environment variable. Command line arguments don't have this limitation, so you can supply anything you want to cmd.
- Notes - Rundll32 and Regsvr are short enough to replace cmd as the initial application. Remember that ".exe" is automatically concatenated to the end of the executable name, so "cmd.exe" becomes "cmd.exe.exe", so you should refrain from specifying the extension.
First published by Matt Nelson of SpecterOps here
To perform this technique, first create an instance of the "MMC20.Application" object:
Next, we are able to use the "ExecuteShellCommand" method of the "Document.ActiveView" property to execute our command:
- Artifacts and Indicators - The executed command is run as a child process of mmc.exe.
- Notes - Execution of mmc.exe via COM seems to be extremely rare, which makes it hard to make this technique to appear as noise to an alert defender.
First published by Matt Nelson here
To perform this technique, first create an instance of the ShellWindows object:
We are able to run an arbitrary command using the "ShellExecute" method of the "Document.Application" property:
- Artifacts and Indicators - Unlike most other methods, ShellWindows does not create a process. Instead, it activates the class instance inside of an existing explorer.exe process, which executes child processes quite regularly. To communicate, the host explorer.exe opens a listening socket on a DCOM port, which should clearly flag this technique. An explorer.exe process with a listening socket should raise your suspicion regardless of this method.
- Limitations - The ShellWindows object represents an open file explorer window. This means trying to create this object on a machine with no open explorer windows returns nothing, making this method unavailable.
- Notes - The ShellWindows class is not associated with a ProgID, and must be created via the CLSID. Of course, all other object may be created using a CLSID as well.
First published by Matt Nelson
To perform this technique, first create an instance of the ShellBrowserWindow object:
We are again able to run a command via the "ShellExecute" method of the "Document.Application" property:
- Artifacts and Indicators - Just like ShellWindows, this method is hosted by an existing explorer.exe process, again having the indicator of an explorer.exe process with a listening socket.
- Limitations - While this object does not require an open explorer window like ShellWindows, it is not available on Windows 7 and earlier versions.
- Notes - The ShellBrowserWindow class also isn't associated with a ProgID.
Visio Addon Execution
First discovered by Cybereason
While not a part of the default Office installation and thus not as widespread, Visio provides a DCOM object that could be used for lateral movement.
To perform this technique, first create an instance of the Visio object. This can be done either via the Visio.Application ProgID, or via the Visio.InvisibleApp ProgID:
Visio addons could be implemented as stand-alone processes, and Visio allows to load any executable as a custom addon. This may be leveraged to facilitate execution:
- Artifacts and Indicators - The addon is run as a direct child process of Visio.
- Notes - Since Visio isn’t as widespread, this method isn't applicable to as many machines as the other methods described here. This means it is even less likely to spawn child processes.
Outlook Execution WIth CreateObject and Shell.Application
This is a variation on a method discovered by Matt Nelson.
The Outlook object allows the instantiation and interaction with arbitrary COM objects via the "CreateObject" method. This lets an attacker interact with COM objects on a remote machine that are normally unexposed by DCOM.
Command line execution can be achieved by creating the Shell.Application object via Outlook:
- Artifacts and Indicators - The command is run as a direct child process of Outlook.
- Notes - One could substitute the "Shell.Application" (which is implemented in the already loaded shell32.dll) object for "Wscript.Shell", but this gives no advantage and provides the additional indicator of the process loading "wshom.ocx".
Arbitrary Library Load
Excel XLL Registration
First published by Ryan Hanson here
Excel is extensible by XLL libraries, which are simply DLLs that export specific functions. The Excel.Application object exposes this functionality via the RegisterXLL method.
- Artifacts and Indicators - The Excel process loads an unknown DLL.
- Notes - While canonical XLLs have the .xll extension and specific exports, the RegisterXLL method will run the DllMain of any dll regardless of file extension and exported functions.
Word WLL Add-in
Word also has an XLL-like add-ins implemented using WLL libraries. These can be added using the "AddIns" property of the Word.Application object:
- Artifacts and Indicators - The Word process loads an unknown library with the WLL extension.
- Limitations - Unlike XLLs, Word add-ins must have the .wll extension. Furthermore, this technique only works on 32-bit Word, as 64-bit Word does not support WLL add-ins.
Arbitrary Script Execution
OutlookScript Execution WIth CreateObject and ScriptControl
First described by Matt Nelson here.
The original technique uses Outlook to access the ScriptControl COM class, which can allow an attacker to run a script supplied in string format:
- Artifacts and Indicators - The ScriptControl object is implemented in msscript.ocx and is seldom used, and an instance of Outlook which loads this legitimately is an extremely rare phenomenon. Additionally, either jscript.dll or vbscript.dll are loaded to run the script itself.
- Limitations - The ScriptControl object is available only in a 32-bit version. As 64-bit processes are unable to load 32-bit inproc objects, 64-bit Outlook is unable to interact with this object.
First discovered by Cybereason
The Visio object provides a direct method to run any line of VBA from a string with the "ExecuteLine" method:
- Artifacts and Indicators - VBE7.dll and ScrRun.dll are loaded into the Visio process
- Notes - The ExecuteLine method allows only for the execution of a single line of code. This is bypassed by using the colon (:) symbol to separate statements on a single line.
Office Fileless Macro Execution
The VBA Engine model in Office is normally inaccesible programmaticaly and needs to be enabled through the "Trust Access to Visual Basic Project" option in the properties menu of every application. This can also be done via the "HKCU\Software\Microsoft\Office\<office version>\<office application name>\Security\accessVBOM" value in the registry for every relevant Office application. Setting these values to 1 remotely (via WMI, for example) allows for the injection and execution of VBA macros into Excel, Word, PowerPoint and Access without supplying a payload carrying document file first.
The macro used for the example will simply run calc.exe:
Executed via Excel:
- Artifacts and Indicators - As described before, enabling these methods requires the manipulation of certain registry keys that are rarely touched remotely, and are occasionally used by malicious macros. This requires the applications to load the Visual Basic Environment (vbe7.dll) library. Additionally, the creation of a new document by any of the applications makes the "Quit" method fail, as the document needs to be saved. This means potential payloads need to somehow handle taking down the parent Office process inconspicuously, to avoid having the enabling process linger in the environment after execution. Access leaves an additional artifact, as unlike the other applications it needs to actually create a database file and save it to a location chosen by the attacker on disk before one is able to insert and execute macros.
- Notes - The AccessVBOM registry value is used by one of the standard Cobalt Strike stagers to create and run an Excel macro that injects stager shellcode into rundll32
Office Macro Execution From Existing Documents
The Excel version of this was first published by Matt Nelson here.
The above COM objects can also be used to run macro payloads embedded in existing documents in an almost identical manner by using methods to open existing documents and then using the "Run" method to run the macro payload.
- Artifacts and Indicators - This method trades the need for a macro for the ability to run a macro filelessly. This means a malicious document needs to be present on a machine and opened by the relevant application for execution to occur. Unless the document is changed, the applications can exit gracefully through the "Quit" method, removing the need to handle this in the payload.
prevention and detection
- Together with the ability to identify which applications were started remotely by DCOM, the artifacts and indicators left by every technique could create strong IoCs.
- Each of these techniques is not a vulnerability, but rather an abuse of a legitimate feature. This means that some environments may actually use these features (we have seen quite a few legitimate instances of Excel running macros remotely, for example), but this is still pretty uncommon. This means individual organizations could try and create a baseline for DCOM usage in their networks, treating non-whitelisted events with suspicion. Most applications of these features are kept in use for historical reasons, and as such, whitelisting should become progressively easier with more DCOM events witnessed
- Creating a DCOM object means an attacker needs to shut it down as well. While most objects mentioned have a handy "Quit" method, some circumstances (such as creating, opening and modifying a document) make the task of shutting down the object harder, as the host application may refuse to terminate. Reckless attackers unable to clean up after execution could leave a very noisy lingering Office process on their target.
- DCOM access to dangerous objects should be prohibited by policy and strictly whitelisted as needed, since denying DCOM access to these objects (via dcomcnfg, for example) will probably not create any unwanted side-effects
- As a matter of fact, installing 32-bit Office on a 64-bit version of Windows does not register appIDs for the relevant applications (it is unknown to me if by mistake or by design), thus "vaccinating" unknowing users against DCOM-based lateral movement. If you didn't know this, and are not suffering from Office related DCOM problems on these machines, it would probably be safe to deny DCOM access to the Office objects on your machines which have x64 Office installed.
DCOM, and especially the Microsoft Office DCOM objects, present a broad attack surface for lateral movement. While these methods leave traces that could be easily detected by a vigilant and informed defender, using them may help an attacker to evade detection and hinder hunting by executing code remotely through mostly unmonitored channels. The vast selection of techniques could help attackers tailor their lateral movement methods to appear as close to noise as possible in a target network. Defenders should apply the prevention advice given, if possible, by closing remote execution channels that are not actively used on the network.
Want to learn how to threat hunt?