Finding and Identifying JScript/VBScript Callable COM Objects
Microsoft JScript and VBScript are two languages that can be used for initial code execution on a new target. This may be done through the use of a phishing payload that leverages .hta files or through the use of trusted binaries to execute a payload on a new target. The use of .hta files specifically is a known attack vector, well documented in places such as the MITRE ATT&CK framework (https://attack.mitre.org/techniques/T1170/).
When looking to emulate an attack on a given network, it is often not as simple as throwing a GitHub Proof of Concept exploit into a file, changing variable names, and then deploying it. Antivirus companies are getting better over time, which means we need to examine more complex methods of modifying our payloads.
One method for modifying a payload is to find new or different calls that can accomplish similar tasks. Modification of a higher-level call that resolves down to a similar or identical Win32 API call will not always be effective but can be a fairly easy first step in payload modification.
Recently, I had the pleasure of modifying some Jscript payloads, looking for ways that we could handle information differently. Specifically, I wanted to determine if I could replace some of the calls being farmed out to .net with more traditional COM objects that would not be reliant on the .net framework being installed.
The requirements to instantiate a COM object inside of J/VBScript are actually quite low. The desired COM object needs to be properly registered and locatable under HKEY_CLASSES_ROOT. The object also needs to have a ProgID. The string underneath the ProgID key is what will be used in the creation call ( new ActiveXObject() || CreateObject() ). You will sometimes see a VersionIndependentProgID, which you may also use if it is listed. Finally, the COM object needs to implement the IDispatch method and support oleautomation.
Two freely available tools that can assist with identifying interfaces on COM objects are Oleviewdotnet (https://github.com/tyranid/oleviewdotnet - Credit to James Forshaw for its creation) and Oleview, (installed with VC++ in Visual studio). Oleviewdotnet is very good for identifying all interfaces and experimenting with calls, where Oleview gives a more in depth look at the typelib for a given COM object. This will directly list attributes such as oleautomation, propget/put, etc. Most of the work can easily be accomplished using Oleviewdotnet, including identification of the default interface. Identification of the default interface is important because a scripting language cannot specify the interface during object instantiation.
Just because you can instantiate an interface of a given COM object does not mean that it should be interacted with from Jscript/VBScript. If something returns an IUnkown object, it cannot be resolved back up to a proper type. With that said, there are still many callable interfaces that I have not witnessed being explored. To show how to find callable interfaces, I’ll walk through the scenario of trying to find a COM object that will perform a check to determine if the target currently has an Internet connection.
Tools Used:
- Oleviewdotnet (https://github.com/tyranid/oleviewdotnet/releases)
- (Optional) Oleview: Installed with Visual studio if you selected the desktop development workload. (VC++)
- Text editor of your choice
- Clean install of a Windows version you want to target (I’m using Windows 10)
- cscript.exe (exists on your Windows host, used for testing)
Finding an Interface:
We want a non-obvious way to perform an online check. There are many basic ways that we can accomplish this, but let's see how it can be accomplished from a COM object.
First, we need to identify a COM object that might want to check for Internet access before performing an action. Let's go ahead and open up Oleviewdotnet. We have a few choices for how to search and each have their merits. For this one, let’s use Registry -> Interfaces. After selecting Interfaces, you will be presented with a massive list. We want to check if we are online, so let's start simple and search "online".
This filters our list from 27074 interfaces to a much more manageable 27. Interfaces that may be callable from J/VBScript will have the option View Type Library when you right-click on them. Let’s take a closer look at IOnlineActivation (right-click view type library). This action will open a new tab with a list of interfaces contained in the type library.
The top tab contains the typelib name. In order to call any of these interfaces, we need to identify what ProgID they belong to. A fairly good way to find this is to open the Prog ID’s tab using Registry -> Prog IDs and search for part of the typelib name (SPPComAPI in this case).
This search will show the IOnlineActivation interface is available via SppComAPI.OnlineActivation. We also see three other interfaces in this list, IDispatch (that will always be there in something we can call), IUnknown (this should always be there in a given COM object), and IElevationConfigurable. Since IElevationConfigurable is also listed under this program ID, we need to identify which interface is the default, as that is the interface referenced when this COM object is created in J/VBScript. The other interface will not be reachable under this application programming interface (API).
Diving into Oleview will allow you to open the SPPComApi typelib again. In this tool, an interface will be explicitly labeled as default. A simpler way is to hover the IDispatch interface in Oleviewdotnet and see what vtable address it has. Then hover the other interfaces and see which one matches. That will be the default interface accessible to J/VBScript. In this case, IOnlineActivation is our default interface.
At this point, we know we can create a COM object using the ProgID SppComAPI.OnlineActivation, and we can call any of the method/list properties from the IOnlineActivation interface. Because we are using Oleviewdotnet, we will see function prototypes for how to call the methods, and what properties are available.
For the current goal of checking Internet connectivity, the CheckServiceReachable property might be interesting. A quick call in code will show if it's useful (worth noting that while CheckServiceReachable is accessed like a property, it executes code like a function call).
Give the above code a test and it will print, “I’m online” when executed on a machine that has an Internet connection and, “I’m all alone” when it doesn’t. Fire-up wireshark and you’ll see the system makes a Domain Name System (DNS) request for activation-v2.sls.microsoft.com, performs a TCP handshake, and then makes an https connection to said site. If this whole process succeeds, then at the very least activation-v2.sls.microsoft.com is accessible.
As may already be obvious, many more interfaces are available, some easily workable from J/VBScript and others less so. Hopefully, if you’re looking to write some new macros or hta files, this knowledge will assist you with an additional avenue of finding potential code paths to accomplish your goals.
References:
- Oleviewdotnet: https://github.com/tyranid/oleviewdotnet
- Oleview: https://docs.microsoft.com/en-us/windows/win32/com/ole-com-object-viewer
- Wireshark: https://www.wireshark.org
- MITRE ATT&CK framework: https://attack.mitre.org/techniques/T1170/