Easily one of the most interesting blogs on windows behaviour is Raymond Chen's The Old New Thing . I noticed he'd recently posted about using "Interactive User" (IU) COM objects to go from an elevated application (in the UAC sense) to the current user for the desktop. What interested me is that registering arbitrary COM objects as IU can have security consequences, and of course this blog entry didn't mention anything about that.
The two potential security issues can be summarised as:
An IU COM object can be a sandbox escape if it has non-default security (for example Project Zero Issue 1079 ) as you can start a COM server outside the sandbox and call methods on the object. An IU COM object can be a cross-session elevation of privilege if it has non-default security ( for example Project Zero Issue 1021 ) as you can start a COM server in a different console session and call methods on the object.I've blogged about this before when I discuss how I exploited a reference cycle bug in NtCreateLowBoxToken (see Project Zero Issue 483 ) and discussed how to use my OleView.NET tool find classes to check. Why do I need another blog post about it? I recently uploaded version 1.5 of my OleView.NET tool which comes with a fairly comprehensive PowerShell module and this seemed like a good opportunity on doing a quick tutorial on using the module to find targets for analysis to see if you can find a new sandbox escape or cross session exploit.
Note I'm not discussing how you go about reverse engineering the COM implementation for anything we find. I also won't be dropping any unknown bugs, but just giving you the information needed to find interesting COM servers.
Getting Started with PowerShell ModuleFirst things first, you'll need to grab the release of v1.5 from the THIS LINK . Unpack it to a directory on your system then open PowerShell and navigate to the unpacked directory. Make sure you've allowed arbitrary scripts to run in PS, then run the following command to load the module.
PS C:\> Import-Module .\OleViewDotNet.psd1
As long as you see no errors the PS module will now be loaded. Next we need to capture a database of all COM registration information on the current machine. Normally when you open the GUI of OleView.NET the database will be loaded automatically, but not in the module. Instead you'll need load it manually using the following command:
PS C:\> Get-ComDatabase -SetCurrent
The Get-ComDatabase cmdlet parses the system configuration for all COM information my tool knowns about. This can take some time (maybe up to a minute, more if you have Process Monitor running), so it'll show a progress dialog. By specifying the -SetCurrent parameter we will store the database as the current global database, for the current session. Many of the commands in the module take a -Database parameter where you can specify the database you want to extract information from. Ensuring you pass the correct value gets tedious after a while so by setting the current database you never need to specify the database explicitly (unless you want to use a different one).
Now it's going to suck if every time you want to look at some COM information you need to run the lengthy Get-ComDatabase command. Trust me, I've stared at the progress bar too long. That's why I implemented a simple save and reload feature. Running the following command will write the current database out to the file com.db:
PS C:\> Set-ComDatabase .\com.db
You can then reload using the following command:
PS C:\> Get-ComDatabase .\com.db -SetCurrent
You'll find this is significantly faster. Worth noting, if you open a 64 bit PS command line you'll capture a database of the 64 bit view of COM, where as in 32 bit PS you'll get a 32 bit view.
Finding Interactive User COM ServersWith the database loaded we can now query the database for COM registration information. You can get a handle to the underlying database object as the variable $comdb using the following command:
PS C:\> $comdb = Get-CurrentComDatabase
However, I wouldn't recommend using the COM database directly as it's not really designed for ease of use. Instead I provide various cmdlets to extract information from the database which I've summarised in the following table:
Command
Description
Get-ComClass
Get list of registered COM classes
Get-ComInterface
Get list of registered COM interfaces
Get-ComAppId
Get list of registered COM AppIDs
Get-ComCategory
Get list of registered COM categories
Get-ComRuntimeClass
Get list of Windows Runtime classes
Get-ComRuntimeServer
Get list of Windows Runtime servers
Each command defaults to returning all registered objects from the database. They also take a range of parameters to filter the output to a collection or a single entry. I'd recommend passing the name of the command to Get-Help to see descriptions of the parameters and examples of use.
Why didn't I expose it as a relational database, say using SQL? The database is really an object collection and one thing PS is good at is interacting with objects. You can use the Where-Object command to filter objects, or Select-Object to extract certain properties and so on. Therefore it's probably a lot more work to build on a native query syntax that just let you write PS scripts to filter, sort and group. To make life easier I have spent some time trying to link objects together, so for example each COM class object has an AppIdEntry property which links to the object for the AppID (if registered). In turn the AppID entry has a ClassEntries property which will then tell you all classes registered with that AppID.
Okay, let's get a list of classes that are registered with RunAs set to "Interactive User" . The class object returned from Get-ComClass has a RunAs property which is set to the name of the user account that the COM server runs as. You also need to only look for COM servers which run out of process, we can do this by filtering for only LocalServer32 classes.