UACME源码浅析

正好今天某位大哥对过UAC有需求,单独抽出来时间看了一下UACME的整体代码,日本人写的代码很有意思,尤其在命名上~笑 ;)

工程结构

https://github.com/hfiref0x/UACME
作者 https://twitter.com/hfiref0x

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
.
├── 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中的目录包括:

  1. Akagi 也就是主要的Bin,其中包含了所有的Methods,绕过UAC的主要方法的源码都在Method目录下,会以UAC绕过方法的发现者的名字来命名源文件。
  2. Akatsuki 又叫做“晓”,WOW64 logger绕过UAC的利用方法的DLL源码
  3. Fubuki 又叫做“暴风雪“,好几个绕过UAC利用的代理DLL,他们都共用了劫持Ole32.dll的方法
  4. Hibiki 又叫做“声音”,AVRF方法绕过UAC的利用方法的DLL源码
  5. Ikazuchi 又叫做”雷声“,利用劫持 comctl32.dll 组件绕过UAC的利用方法的DLL源码
  6. Inazuma 又叫做“闪电”,SHIM相关利用的绕过UAC的利用方法的EXE源码
  7. Kamikaze 又叫做“神风”,未在工程文件中引用,MMC劫持方法利用的MSC文件
  8. Kongou 又叫做“金刚”,利用Hybrid方法绕过UAC的Dll,已经排除在新工程中的引用了
  9. Naka 又叫做“空气”,压缩及亦或编码的小工具源码
  10. 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多种方法,归类起来利用方式主要是两大类:

  1. 各类UAC白名单程序的DLL劫持
  2. 各类提升权限的COM接口利用

其余还有若干小的方法,具体的情况可以参考UACME项目的README。我们今天的重点仍旧放在源码上,只是兼谈一下关于UAC绕过的一些知识。

摘取单一方法

这里以41号方法来分析,如何从Akagi的大项目中单独提取某个方法。我们从工程Akagi的Main.c开始入手,找到程序的函数入口Main(),分析函数执行流程如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
ucmMain()
|
|
|
ucmInit(&Method)
|
|
|
supMasqueradeProcess()
|
|
|
MethodsManagerCall(Method)

其中Method是个枚举类型 _UCM_METHOD ,MethodsManagerCall会在调用前做一些准备工作,包括如果需要额外的Payload(如代理Dll文件等),会从资源文件中解密出来。MethodsManagerCall会根据传入的Method号在ucmMethodsDispatchTable这个结构体找到调用方法的相关配置,41号方法不需要额外的Paydload,其对应到的源码位于methods/api0cradle.c ,所以整个调用流程是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
UCM_API(MethodCMLuaUtil)
|
|
|
ucmCMLuaUtilShellExecMethod()
|
|
|
ucmMasqueradedCoGetObjectElevate()
|
|
|
CMLuaUtil->lpVtbl->ShellExec()
|
|
|
|
CMLuaUtil->lpVtbl->Release()

ucmCMLuaUtilShellExecMethod函数封装了一个典型的Elevated COM接口调用过程,具体方式可以参见最后第二号引用。但是需要注意一点的是,在整个过程中ucmMasqueradedCoGetObjectElevate函数封装的CoGetObject这个API,总的来说有两点:

  1. 首先自然是调用COM时,必须使用 CoInitialize 进行初始化
  2. CoGetObject 如果使用了BIND_OPTS3结构体填充第二个参数,则必须要初始化当前进程的窗口,在提升权限授权时,如果此参数为空则默认会取当前活动窗口。

其实回过头去看ucmInit函数中,如上的处理他已经都做了。我们还漏掉了supMasqueradeProcess函数没有分析,其实这个函数实现了PEB Patch的功能,用来伪造进程上下文。在以前最最经典的Win7 Sysprep方式的绕过UAC方法下,我们需要复制一个DLL到指定目录,前面也说过安装文件的过程中向系统盘符的敏感路径复制文件时,是一定会弹出UAC框的,但是使用Explorer调用COM接口IFileOperation的方式则不会有提示,Sysprep Bypass Uac中最老的利用方式是注入Dll到Explorer进程中的。

所以总结起来,摘取41号的单一方法就是:

  1. CoInitialize 初始化
  2. CreateWindow 创建窗体
  3. PEB Patch
  4. 调用 Elevated COM 接口中的特别方法

如41号使用了ICMLuaUtil这个接口中的ShellExec方法,来达到执行命令的目标。

Powershell版本

留为作业吧,实在懒得写了 = =

结语

行文时间仓促,UACME的代码还有很多值得阅读的小细节以及处理方式,最后感谢 @hFireF0x 整理了多种过UAC的方法。
关于如何进行UAC绕过方法Fuzz的过程,可以参考FuzzSec一篇非常不错的 Paper,这里也一并附上链接,感谢他们带来的知识。

参考