BypassUAC
本篇主要介绍如何以ICMLuaUtil
方式BypassUAC
,主要内容如下:
- 过掉
UAC
提示框的方法总结 UACME
项目- 什么类型的
COM interface
可以利用? - 如何快速找到系统中的所有可利用的
COM
组件? - 定位
ICMLuaUtil
的虚函数表vftable
- 如何调用
ICMLuaUtil.ShellExec
执行命令?- C++ version
- CSharp version
- 两个注意点
DLL
形式- C++ dll导出函数方式
- C# dll导出函数方式
- 一个坑
- 值得研究的
C2
推荐
过掉UAC
提示框的方法总结
这里主要说的是dll
的形式,通过上面的实操,可以发现有两种方法:
- 基于白名单程序绕过
UAC
- 伪装进程
PEB
绕过UAC
- 无文件技术
伪装进程的方式其实也可以算做借助了白名单,但是没有直接调用白名单进程,所以单独列出来了。
基于白名单程序绕过UAC
有些系统程序是直接获取管理员权限,而不会触发UAC弹框,这类程序称为白名单程序,例如:slui.exe
、wusa.exe
、taskmgr.exe
、msra.exe
、eudcedit.exe
、eventvwr.exe
、CompMgmtLauncher.exe
,rundll32.exe
,explorer.exe
等等。
常见的利用方式有:
DLL
注入(RDI
技术),一般注入到常驻内存的可信进程,如:explorer
DLL
劫持,常和注册表配合使用达到劫持目的
伪装进程PEB
绕过UAC
上面在利用COM
接口的ShellExec
执行命令的时候,因为执行该操作的进程身份是不可信的,所以会触发UAC
弹窗。为了能够迷惑系统,通过修改PEB
结构,让系统误认为这是一个可信进程,伪装的可信进程可以是calc.exe
、rundll32.exe
、explorer.exe
等。
利用火绒剑查看进程信息,可以看到已经识别为可信进程了:
关于PEB
的结构,可以参照这里。
无文件技术
“无文件攻击”是一种攻击策略,其出发点就是避免将恶意文件放在磁盘上,以逃避安全检测。无文件四种攻击形式:
- 恶意文档
比如:在
word
中加入恶意的宏代码实现命令执行,又或者邮件中。 - 恶意脚本 常用的脚本引擎:powershell.exe,cscript.exe,cmd.exe 和 mshta.exe,同样不生成恶意二进制文件。
- 恶意本地程序交互
例如:
rundll32.exe
、wmi
等,详细参考这里。 - 恶意内存代码
直接生成纯
shellcode
,通过其他方式加载到内存执行。
UACME项目
项目地址:https://github.com/hfiref0x/UACME
项目总结了50多种绕过UAC
的方式,并且列出具备auto-elevate
能力的UAC
白名单程序或接口。
利用方式主要可以分为两大类:
- 各类
UAC
白名单程序的DLL劫持(Dll Hijack
) - 各类提升权限的
COM
接口利用(Elevated COM interface
)
项目的主程序为Akagi
,其中包含了所有的method
,使用vs2019
本地编译后可以使用akagi32 41
或者akagi64 41
启动程序,41
这个指的是README
中描述的方法索引,运行后可以直接得到管理员权限的cmd
窗口。
项目的Source
目录存储的是所有子项目的源码,其中Source/Shared
存放的是被所有子项目共同引用的一些函数,本篇主要利用Akagi
和Yuubari
这两个Project
来探究一下如何利用COM
接口提升权限。
什么类型的COM interface
可以利用?
以项目中索引为41
的方法为例:
Author: Oddvar Moe
Type: Elevated COM interface
Method: ICMLuaUtil
Target(s): Attacker defined
Component(s): Attacker defined
Implementation: ucmCMLuaUtilShellExecMethod
Works from: Windows 7 (7600)
Fixed in: unfixed ?
How: -
该方法的目标接口是ICMLuaUtil
,对应Akagi
项目中具体实现函数为ucmCMLuaUtilShellExecMethod
,在项目中的methods/api0cradle.c
文件中可以找到该方法的定义:
观察发现这里利用的是CMSTPLUA
组件的ICMLuaUtil
接口。
我的测试系统Windows 10 (1909)
,使用OleViewDotNet工具可以查看系统中的COM
接口属性信息,注意需要以管理员权限运行。
打开CLSIDs
窗口搜索cmstplua
,可以快速定位该组件:
右键查看CMSTPLUA
组件的Elevation
属性:
这里的Enabled
和Auto Approval
值都是True
表示这个组件可以用来绕过UAC
认证,这是第一点。
第二点是目标接口ICMLuaUtil
需要有一个可以执行命令的地方,通过在CISIDs
窗口鼠标悬浮在ICMLuaUtil
上,可以看到该接口对应的二进制文件为cmlua.dll
:
虚函数偏移为cmlua.dll+0x6360
,通过IDA
打开该系统文件(c:\windows\system32\cmlua.dll
),跳到虚函数表的位置,可以看到ICMLuaUtil
接口的虚函数表:
摘出来看接口函数如下:
01 QueryInterface(_GUID const &,void * *)
02 AddRef(void)
03 Release(void)
04 SetRasCredentials(ushort const *,ushort const *,ushort const *,int)
05 SetRasEntryProperties(ushort const *,ushort const *,ushort * *,ulong)
06 DeleteRasEntry(ushort const *,ushort const *)
07 LaunchInfSection(ushort const *,ushort const *,ushort const *,int)
08 LaunchInfSectionEx(ushort const *,ushort const *,ulong)
09 CreateLayerDirectory(ushort const *)
10 ShellExec(ushort const *,ushort const *,ushort const *,ulong,ulong)
11 SetRegistryStringValue(int,ushort const *,ushort const *,ushort const *)
12 DeleteRegistryStringValue(int,ushort const *,ushort const *)
13 DeleteRegKeysWithoutSubKeys(int,ushort const *,int)
14 DeleteRegTree(int,ushort const *)
15 ExitWindowsFunc(void)
16 AllowAccessToTheWorld(ushort const *)
17 CreateFileAndClose(ushort const *,ulong,ulong,ulong,ulong)
18 DeleteHiddenCmProfileFiles(ushort const *)
19 CallCustomActionDll(ushort const *,ushort const *,ushort const *,ushort const *,ulong *)
20 RunCustomActionExe(ushort const *,ushort const *,ushort * *)
21 SetRasSubEntryProperties(ushort const *,ushort const *,ulong,ushort * *,ulong)
22 DeleteRasSubEntry(ushort const *,ushort const *,ulong)
23 SetCustomAuthData(ushort const *,ushort const *,ushort const *,ulong)
其中第10
个函数ShellExec
从IDA
中看到该函数调用了ShellExecuteEx
这个Windows API
实现了命令执行:
通过对ICMLuaUtil
接口的分析,可以看出可以用来BypassUAC
执行命令的COM
组件需要有两个特点:
elevation
属性启用,且开启Auto Approval
;COM
组件中的接口存在可以命令执行的地方,例如ICMLuaUtil
的ShellExec
;
如何快速找到系统中的所有可利用的COM
组件?
除了通过上面的方式在OleView
中手动去找,还可以通过UACMe
项目提供的Yuubari
工具快速查看系统UAC
设定信息以及所有可以利用的程序和COM
组件,使用方法如下:
使用VS2019
加载Yuubari
,生成后会得到二进制文件UacInfo64.exe
,运行后在同目录生成一个log
文件记录所有输出结果:
从这里面可以找到所有的Autoelevated COM objects
,包括CMSTPLUA
组件的信息:
定位ICMLuaUtil
的虚函数表vftable
通过分析UACMe
中的ucmCMLuaUtilShellExecMethod
实现可以知道想要利用COM
接口,需要知道这几个东西:
- 标识
COM
组件的GUID
,即CLSID
- 标识
interface
的GUID
,即IID
- 该接口的虚函数表,主要用来找到
ShellExec
的函数偏移
前两个可以很容易找到,虚函数表可以通过OleView
提示的虚函数表位置偏移找到,这里再说一种通用的方法,完全利用IDA
。
第一步,用IDA
打开cmlua.dll
;
第二步,在左侧函数列表中搜索destructor
或者constructor
,双击后跳转后,上下找找可以看到调用vftable
的地方:
双击跳转到变量定义位置,就可以找到虚函数表!
参考:Get interface definition of undocumented COM objects
如何调用ICMLuaUtil.ShellExec
执行命令?
c++ version
代码是从UACMe
中摘出来的,放在了github
上。
代码地址:BypassUAC
如果直接把ucmCMLuaUtilShellExecMethod
这个函数直接摘出来,会发现还是会弹UAC
的窗:
在vs2019
中可以对Akagi
项目调试,项目属性中设置命令参数为41
:
直接在函数ucmCMLuaUtilShellExecMethod
的地方下断:
通过分析函数调用链,发现ucmMain
在调用对应方法之前先调用了supMasquradeProcess
这个函数。
该函数负责进行PEB
的伪装,将自己的进程信息伪装成为c:\windows\explorer.exe
这个系统的可信进程,这样才能绕过UAC
认证窗口,所以在使用COM
组件提权之前需要先伪装一下进程才可以:
这种方式,因为修改的是自己的进程信息,并不是修改其他进程,所以一般杀软、AV是不会拦的。
CSharp version
代码摘自Moriarty2016和p0wnedShell。
代码地址:BypassUAC_csharp
两个注意点
C#
版本的代码中需要注意ICMLuaUtil
接口的定义,其继承自IUnKnown,该接口定义函数如下:
IUnknown::AddRef
IUnknown::QueryInterface
IUnknown::QueryInterface
所以在定义ICMLuaUtil
的时候,有以下两点需要注意:
- 指明继承自
IUnKnown
接口; - 继承的函数不需要加上,
C#
会自动添加;
关于C#
接口的知识,可以从这里了解更多。
DLL 形式
如何使用?
dll
可以使用系统可信进程rundll32.exe
进行加载,这样也不需要调用MarquradePEB
。
C++ dll导出函数的方式
代码地址:BypassUAC_Dll
导出的函数为BypassUAC
,导出方式直接新建一个def
文件,格式参考这里,内容如下:
LIBRARY BypassUAC
EXPORTS
BypassUAC
生成之后通过CFF Explorer
查看导出表:
利用rundll32.exe .\BypassUAC_Dll.dll,BypassUAC
命令测试后,bypass
成功!
C# 导出dll函数的方式
代码地址:BypassUAC_Dll_csharp
C#
导出dll函数的方式有两种:
- 使用
DllExport
这个NuGet
包 - 通过
IL
反编译的方式
DllExport
默认C#
导入其他库函数,可以使用[DllImport]
,但是不支持[DllExport]
,通过NuGet
包管理器安装DllExport
这个包可以实现这个功能。
在vs
中可以对指定项目安装这个包:
安装之后,直接使用[DllExport]
导出BypassUAC
函数即可:
重新生成dll
文件,在CFF
中查看,已经导出成功:
IL 反编译
如果了解Java
的,java
文件首先编译成class
,然后交给JVM
去解释成机器码。.net
为了跨平台,这里类似,同样有一个中间语言的文件,但不是class
了,而是IL
。
通过修改IL
文件,也可以导出dll
函数。
首先去除[DllExport]
后将dll
代码编译,编译后的dll
文件是看不到Export Directory
的。
然后ildasm
把dll
文件反编译成il
文件,命令如下:
ildasm BypassUAC_Dll_csharp.dll /out=BypassUAC_Dll_csharp.il
打开生成的BypassUAC_Dll_csharp.il
文件,找到需要导出的目标函数BypassUAC
,在函数开头处添加如下代码:
.export [1]
保存后,需要使用ilasm
再把il
编译成dll
文件,这里遇到一个坑,如果按照如下命令进行编译:
ilasm BypassUAC_Dll_csharp.il /dll /out=BypassUAC_Dll_csharp_exp.dll
发现使用rundll32.exe .\BypassUAC_Dll_csharp_exp.dll,BypassUAC
运行后没有任何反应。
在BypassUAC
函数开头处添加一个MessageBox
弹窗,再次运行弹框之后,附加到windbg
调试,让程序再次跑起来,运行结束后在windbg
中可以看到:
进程加载的cmlua.dll
文件并不是system32
目录,而是SysWOW64
的,SysWOW64
放的是32
位系统文件,程序为什么去加载的是32
位的,使用CFF
看一下生成的dll
文件类型:
问题的根源就是这里,利用IL
转之前的dll
是64
位的,转之后变成了32
位的,解决方法很简单,使用ilasm
的时候添加一个/X64
参数就可以了:
ilasm BypassUAC_Dll_csharp.il /dll /X64 /out=BypassUAC_Dll_csharp_exp.dll
这样就可以成功的BypassUAC
了。
值得研究的C2推荐
- Python
- Empire,官方已经不维护了不推荐用,但是值得研究借鉴
- Pupy,很适合玩Python的研究
- SILENTTRINITY,利用的
.net DLR
方式实现,动态加载不落地 - PoshC2
- .NET
- Covenant,网页版的C2
其他参考
- T1088