UACME源码浅析
正好今天某位大哥对过UAC有需求,单独抽出来时间看了一下UACME的整体代码,日本人写的代码很有意思,尤其在命名上~笑 ;)
工程结构
https://github.com/hfiref0x/UACME 作者 https://twitter.com/hfiref0x
.
├── Compiled
├── LICENSE.md
├── README.md
├── Source
│ ├── Akagi
│ ├── Akatsuki
│ ├── Fubuki
│ ├── Hibiki
│ ├── Ikazuchi
│ ├── Inazuma
│ ├── Kamikaze
│ ├── Kongou
│ ├── Naka
│ ├── Shared
│ ├── Yuubari
│ └── uacme.sln
└── Please indicate the origin source of this articles
Compiled
包含已经编译好的Bin,其中囊括了README.md中所统计的所有方法。Source
中的目录包括:
- Akagi 也就是主要的Bin,其中包含了所有的Methods,绕过UAC的主要方法的源码都在
Method
目录下,会以UAC绕过方法的发现者的名字来命名源文件。 - Akatsuki 又叫做“晓”,WOW64 logger绕过UAC的利用方法的DLL源码
- Fubuki 又叫做“暴风雪“,好几个绕过UAC利用的代理DLL,他们都共用了劫持Ole32.dll的方法
- Hibiki 又叫做“声音”,AVRF方法绕过UAC的利用方法的DLL源码
- Ikazuchi 又叫做”雷声“,利用劫持 comctl32.dll 组件绕过UAC的利用方法的DLL源码
- Inazuma 又叫做“闪电”,SHIM相关利用的绕过UAC的利用方法的EXE源码
- Kamikaze 又叫做“神风”,未在工程文件中引用,MMC劫持方法利用的MSC文件
- Kongou 又叫做“金刚”,利用Hybrid方法绕过UAC的Dll,已经排除在新工程中的引用了
- Naka 又叫做“空气”,压缩及亦或编码的小工具源码
- Yuubari Aka UACView用来查看相关UAC的设定信息,以及扫描存在可利用的程序的工具
方法浅析
我们来谈一谈绕过UAC的总的方法论。首先试着分别在普通用户已经管理员模式下的CMD中敲入whoami /all
,结果中你能看到权限令牌标识,事实上UAC就是控制在这些令牌赋值给出提示的,依照与不同权限有时也会弹出需要输入密码以验证的提示。在一些古老的远控中(跑在Nt5上),经常能看到使用API来获取SeDebugPrivilege这个权限的代码。
在研究一些对抗方法的过程中,我们可以从“安全总是要让步于业务”的这个不成文的规则入手,举一个简单例子:我们在开启UAC的情况下,向安装位置在%PROGRAMFILES%安装文件时,总会弹出UAC提示,但是我们安装完成后,在进行程序卸载时却不会弹出任何UAC提示,细心的思考一下,你可能就会开始琢磨其中的端倪。本质上是因为Widnows为这些程序(或者接口)开启了autoElevate(参考 https://technet.microsoft.com/en-us/library/2009.07.uac.aspx)
也就是说Windows系统本身维护了一批这样的在UAC白名单中的程序,至于如何去Fuzz这些程序不再本文的讨论范围当中。
UACME中总结了大约40多种方法,归类起来利用方式主要是两大类:
- 各类UAC白名单程序的DLL劫持
- 各类提升权限的COM接口利用
其余还有若干小的方法,具体的情况可以参考UACME项目的README。我们今天的重点仍旧放在源码上,只是兼谈一下关于UAC绕过的一些知识。
摘取单一方法
这里以41号方法来分析,如何从Akagi的大项目中单独提取某个方法。我们从工程Akagi的Main.c开始入手,找到程序的函数入口Main(),分析函数执行流程如下:
ucmMain()
|
|
|
ucmInit(&Method)
|
|
|
supMasqueradeProcess()
|
|
|
MethodsManagerCall(Method)
其中Method是个枚举类型 _UCM_METHOD
,MethodsManagerCall
会在调用前做一些准备工作,包括如果需要额外的Payload(如代理Dll文件等),会从资源文件中解密出来。MethodsManagerCall
会根据传入的Method号在ucmMethodsDispatchTable
这个结构体找到调用方法的相关配置,41号方法不需要额外的Paydload,其对应到的源码位于methods/api0cradle.c
,所以整个调用流程是:
UCM_API(MethodCMLuaUtil)
|
|
|
ucmCMLuaUtilShellExecMethod()
|
|
|
ucmMasqueradedCoGetObjectElevate()
|
|
|
CMLuaUtil->lpVtbl->ShellExec()
|
|
|
|
CMLuaUtil->lpVtbl->Release()
ucmCMLuaUtilShellExecMethod
函数封装了一个典型的Elevated COM接口调用过程,具体方式可以参见最后第二号引用。但是需要注意一点的是,在整个过程中ucmMasqueradedCoGetObjectElevate
函数封装的CoGetObject
这个API,总的来说有两点:
- 首先自然是调用COM时,必须使用
CoInitialize
进行初始化 - 在
CoGetObject
如果使用了BIND_OPTS3结构体填充第二个参数,则必须要初始化当前进程的窗口,在提升权限授权时,如果此参数为空则默认会取当前活动窗口。
其实回过头去看ucmInit
函数中,如上的处理他已经都做了。我们还漏掉了supMasqueradeProcess
函数没有分析,其实这个函数实现了PEB Patch的功能,用来伪造进程上下文。在以前最最经典的Win7 Sysprep方式的绕过UAC方法下,我们需要复制一个DLL到指定目录,前面也说过安装文件的过程中向系统盘符的敏感路径复制文件时,是一定会弹出UAC框的,但是使用Explorer调用COM接口IFileOperation
的方式则不会有提示,Sysprep Bypass Uac中最老的利用方式是注入Dll到Explorer进程中的。
所以总结起来,摘取41号的单一方法就是:
- CoInitialize 初始化
- CreateWindow 创建窗体
- PEB Patch
- 调用 Elevated COM 接口中的特别方法
如41号使用了ICMLuaUtil这个接口中的ShellExec方法,来达到执行命令的目标。
Powershell版本
留为作业吧,实在懒得写了 = =
结语
行文时间仓促,UACME的代码还有很多值得阅读的小细节以及处理方式,最后感谢 @hFireF0x 整理了多种过UAC的方法。 关于如何进行UAC绕过方法Fuzz的过程,可以参考FuzzSec一篇非常不错的 Paper,这里也一并附上链接,感谢他们带来的知识。
参考
- Method 41 的原来的利用方式 https://msitpros.com/?p=3960
- The COM Elevation Moniker https://msdn.microsoft.com/en-us/library/windows/desktop/ms679687(v=vs.85).aspx
- CoGetObject https://msdn.microsoft.com/en-us/library/windows/desktop/ms678805(v=vs.85).aspx
- FuzzySec指出如果其中利用了COM方法,必须要使用注入到相关进程(如Explorer)或者PEB Patch之后才可以不弹出UAC提示框 https://msdn.microsoft.com/en-us/library/windows/desktop/ms678805(v=vs.85).aspx