UAC 实现原理及绕过方法

0x00 UAC 工作流程

UAC 是微软在 Windows Vista 以后版本引入的一种安全机制,

通过 UAC,应用程序和任务可始终在非管理员帐户的安全上下文中运行,除非管理员特别授予管理员级别的系统访问权限。UAC 可以阻止未经授权的应用程序自动进行安装,并防止无意中更改系统设置。

https://msdn.microsoft.com/en-us/library/bb384608.aspx

从图上可以看到,如果要获取管理员权限,通过的路径有以下几条:
1,进程已经拥有管理权限控制;
2,进程被用户允许通过管理员权限运行。

0x01 UAC 实现方法(用户登陆过程)

ACL(Access Control List):Windows 中所有资源都有 ACL ,这个列表决定了拥有何种权限的用户/进程能够这个资源。
在开启了 UAC 之后,如果用户是标准用户, Windows 会给用户分配一个标准 Access Token.
如果用户以管理员权限登陆,会生成两份访问令牌,一份是完整的管理员访问令牌(Full Access Token),一份是标准用户令牌。一般情况下会以标准用户权限启动 Explorer.exe 进程。如果用户同意,则赋予完整管理员权限访问令牌进行操作。

0x02 UAC 架构

0x03 触发UAC

UAC需要授权的动作包括:
配置Windows Update
增加或删除用户账户
改变用户的账户类型
改变UAC设置
安装ActiveX
安装或移除程序
安装设备驱动程序
设置家长控制
将文件移动或复制到Program Files或Windows目录
查看其他用户文件夹
via Wiki

0x04 UAC 虚拟化

UAC 虚拟化(Virtualization)也被称为重定向(Data Redirection)。在权限判定的过程中,如果用户的权限没有达到程序所需的权限,UAC 就会重定向该文件夹。例如,如果程序试图写入到 C:\Program Files\Contoso\Settings.ini目录下,但用户没有写入权限,这个写操作就会被重定向至 C:\Users\Username\AppData\Local\VirtualStore\Program Files\contoso\settings.ini.
UAC 虚拟化分为两个部分,文件虚拟化和注册表虚拟化。

要注意的是,在以下情况下,虚拟化不可用:

  • 64 位程序
  • 非交互式程序
  • 模拟令牌的进程 (Processes that impersonate)
  • 内核模式调用方
  • 带有 requestedExecutionLevel(请求执行等级)的可执行程序

文件虚拟化(File Virtualization)


Luafv.sys实现的是改变写入文件位置。

注册表虚拟化


Ntoskrnl.exe实现的是改变写入注册表位置。

0x05 UAC 逆向分析

先使用 procexp 查看现有进程

然后使用管理员权限运行一个文件以弹出 UAC 提示框,可以看到多出一个进程consent.exe

这个进程中有一个 Dll appinfo,
UAC 主要的实现文件在于 appinfo.dll 这个文件,
先查看一下appinfo.dllstring,可以直接在这个网站看,用rehacker查看不出,原因未知:

100	Application Information
101	Facilitates the running of interactive applications with additional administrative privileges. If this service is stopped, users will be unable to launch applications with the additional administrative privileges they may require to perform desired user tasks.
200	User Account Control: Behavior of the elevation prompt for administrators in Admin Approval Mode
201	User Account Control: Behavior of the elevation prompt for standard users
202	User Account Control: Detect application installations and prompt for elevation
203	User Account Control: Run all administrators in Admin Approval Mode
204	User Account Control: Virtualize file and registry write failures to per-user locations
205	User Account Control: Only elevate executables that are signed and validated
206	User Account Control: Switch to the secure desktop when prompting for elevation
207	User Account Control: Admin Approval Mode for the Built-in Administrator account
208	User Account Control: Only elevate UIAccess applications that are installed in secure locations
225	User Account Control: Allow UIAccess applications to prompt for elevation without using the secure desktop
251	Prompt for credentials on the secure desktop
252	Prompt for consent on the secure desktop
253	Elevate without prompting
254	Automatically deny elevation requests
255	Prompt for credentials
256	Prompt for consent
257	Prompt for consent for non-Windows binaries

可以知道这个dlluac直接相关了。
下面在 Windows 10 平台下使用 IDA 对其进行逆向分析。
查看一下导出函数,会发现其使用的 RPCRT4 Library 较多。

RPC Functions(Remote Procedure Call),使得一个程序可以调用另一计算机的子程序,顺便一提,本地过程调用(LPC,Local Procedure Call)则是在本机进程间进行通讯。
这个 dll 是通过注册LPC接口进行调用的。
然后上 MSDN 看一看关键的库的作用:

RpcServerInqBindings :Returns a pointer to a pointer to a vector of server binding handles.
RpcServerRegisterIfEx:The RpcServerRegisterIfEx function registers an interface with the RPC run-time library.

进入RpcServerRegisterIfEx查看一下交叉引用:

进入其中一个(反正都是相近的)查看:

.text:0000000180004140
.text:0000000180004140 MaxCalls        = dword ptr -18h
.text:0000000180004140 IfCallback      = qword ptr -10h
.text:0000000180004140 BindingVector   = qword ptr  8
.text:0000000180004140 arg_8           = qword ptr  10h
.text:0000000180004140
.text:0000000180004140 ; FUNCTION CHUNK AT .text:0000000180007B1C SIZE 000000F4 BYTES
.text:0000000180004140
.text:0000000180004140                 mov     [rsp+arg_8], rbx
.text:0000000180004145                 push    rdi
.text:0000000180004146                 sub     rsp, 30h
.text:000000018000414A                 xor     edi, edi
.text:000000018000414C                 lea     rcx, Protseq    ; "ncalrpc"
.text:0000000180004153                 xor     r8d, r8d        ; SecurityDescriptor
.text:0000000180004156                 mov     [rsp+38h+BindingVector], rdi
.text:000000018000415B                 lea     edx, [rdi+0Ah]  ; MaxCalls
.text:000000018000415E                 call    cs:__imp_RpcServerUseProtseqW
.text:0000000180004164                 mov     ebx, eax
.text:0000000180004166                 test    eax, eax
.text:0000000180004168                 jnz     loc_180007B1C
.text:000000018000416E                 lea     rcx, [rsp+38h+BindingVector] ; BindingVector
.text:0000000180004173                 call    cs:__imp_RpcServerInqBindings
.text:0000000180004179                 mov     ebx, eax
.text:000000018000417B                 test    eax, eax
.text:000000018000417D                 jnz     loc_180007B1C
.text:0000000180004183                 mov     [rsp+38h+IfCallback], rdi ; IfCallback
.text:0000000180004188                 lea     r9d, [rdi+29h]  ; Flags
.text:000000018000418C                 xor     r8d, r8d        ; MgrEpv
.text:000000018000418F                 mov     [rsp+38h+MaxCalls], 4D2h ; MaxCalls
.text:0000000180004197                 xor     edx, edx        ; MgrTypeUuid
.text:0000000180004199                 lea     rcx, unk_18000FD00 ; IfSpec
.text:00000001800041A0                 call    cs:__imp_RpcServerRegisterIfEx
.text:00000001800041A6                 mov     ebx, eax
.text:00000001800041A8                 test    eax, eax
.text:00000001800041AA                 jnz     loc_180007B1C
.text:00000001800041B0                 lea     edi, [rax+1]
.text:00000001800041B3                 xor     r8d, r8d        ; MgrEpv
.text:00000001800041B6                 lea     rax, ?AiCOMSecurityCallBack@@YAJPEAX0@Z ; AiCOMSecurityCallBack(void *,void *)
.text:00000001800041BD                 xor     edx, edx        ; MgrTypeUuid
.text:00000001800041BF                 mov     [rsp+38h+IfCallback], rax ; IfCallback
.text:00000001800041C4                 lea     r9d, [rbx+69h]  ; Flags
.text:00000001800041C8                 lea     rcx, unk_18000FCA0 ; IfSpec
.text:00000001800041CF                 mov     [rsp+38h+MaxCalls], 4D2h ; MaxCalls
.text:00000001800041D7                 call    cs:__imp_RpcServerRegisterIfEx
.text:00000001800041DD                 mov     ebx, eax
.text:00000001800041DF                 test    eax, eax
.text:00000001800041E1                 jnz     loc_180007B1C
.text:00000001800041E7                 lea     edi, [rax+5]
.text:00000001800041EA                 xor     r8d, r8d        ; MgrEpv
.text:00000001800041ED                 lea     rax, ?AiMSISecurityCallBack@@YAJPEAX0@Z ; AiMSISecurityCallBack(void *,void *)
.text:00000001800041F4                 xor     edx, edx        ; MgrTypeUuid
.text:00000001800041F6                 mov     [rsp+38h+IfCallback], rax ; IfCallback
.text:00000001800041FB                 lea     r9d, [rbx+69h]  ; Flags
.text:00000001800041FF                 lea     rcx, unk_18000FC40 ; IfSpec
.text:0000000180004206                 mov     [rsp+38h+MaxCalls], 4D2h ; MaxCalls
.text:000000018000420E                 call    cs:__imp_RpcServerRegisterIfEx

为了防止眼瞎,看一下有颜色的:

RpcServerRegisterIfEx具有多个参数,不应该过多关注其本身,这个函数是用来注册 LPC/RPC 接口的,那么就要找出他到底注册了什么借口。
说到这里,要先了解一下 Windows 的进程创建。

http://blog.csdn.net/myjisgreat/article/details/53262932,其中AicLaunchAdminProcess是用以创建管理员进程的。
搜索一下也可以验证 UAC 中使用到了这个接口。

梳理一下,在触发 UAC 时,系统会创建一个consent.exe进程,该进程用以确定是否创建管理员进程(通过白名单和用户选择判断),然后creatprocess.

请求进程将要请求的进程cmdline和进程路径通过LPC接口传递给appinfo的RAiLuanchAdminProcess函数,该函数首先验证路径是否在白名单中,并将结果传递给consent.exe进程,该进程验证被请求的进程签名以及发起者的权限是否符合要求,然后决定是否弹出UAC框让用户进行确认。这个UAC框会创建新的安全桌面,屏蔽之前的界面。同时这个UAC框进程是SYSTEM权限进程,其他普通进程也无法和其进行通信交互。用户确认之后,会调用CreateProcessAsUser函数以管理员权限启动请求的进程。

1x00 UAC Bypass

目前公开的方法中,有以下几种方法绕过 UAC:
1,白名单提权机制;如Wusa.exe Bypass UAC,infDefault.exe Bypass UAC,PkgMgr.exe Bypass UAC等。
2,DLL 劫持;
3,Windows 自身漏洞提权;
4,远程注入;
5,COM 接口技术。

其余的如通过计划任务、路径欺骗等方式不算入绕过,因为这是经过用户确认

1x01 无文件白名单提权机制

sdclt.exe实现无文件绕过UAC

原文:
https://enigma0x3.net/2017/03/17/fileless-uac-bypass-using-sdclt-exe/
sdclt.exe是 Windows 7 模式下的备份与还原文件,在我的 Windows 10 下位于C:\Windows\WinSxS\amd64_microsoft-windows-safedocs-main_31bf3856ad364e35_10.0.10586.494_none_91de6b09c5f6a4d2目录下。
首先使用sigcheck这个工具对文件是否自动能提权进行查看:

>sigcheck.exe -m sdclt.exe


对这个文件进行反汇编分析:

其中,test eax,eax是标志位置位。
_wcsicmp是一个比较函数,如果参数为/KickOffJob则继续向下执行:

其中,xor ecx,ecx是类似于 eax置零,他将 CPU 状态重置以继续执行下面的指令。
下面对sub_140071B08进行分析:

查看 off_14008F1A0,该函数作用为Hidden_Window,即隐藏当前窗口,右键重命名一下方便查看。
跳入 140071B63 进行查看,可以知道这是一个提升权限的函数,同样地右键重命名。

loc_140071B63:
mov     r9d, 1
lea     rdx, aSxshellexecute ; "SxShellExecuteWithElevate"
mov     r8d, 56Ah
lea     rcx, [rsp+108h+var_E8] ; Load Effective Address
call    sub_140056A68   ; Call Procedure

返回之前的函数,命名为Hidden&Elevate,这时候整体结构比较清晰了,

lea     r9, aKickoffjob ; "/KICKOFFJOB"
mov     edx, r13d
lea     r8, aSystemrootSyst ; "%systemroot%\\system32\\sdclt.exe"
xor     ecx, ecx        ; Logical Exclusive OR
call    Hidden_Elevate  ; Call Procedure
mov     [rsp+0F0h+var_C0], eax
test    eax, eax        ; Logical Compare
jns     short loc_140002CB5 ; Jump if Not Sign (SF=0)

总结以上的流程如下:
1,启动sdclt.exe进程;
2,校验是否为KICKOFFJOB参数,若为该参数则启动%systemroot%\system32\sdclt.exe
3,对该进程进行提权。

使用procmon运行并分析:

然后改注册表就行(未实现……键值不在了)。
这个博主很多方法都类似这个,可以看一看(不过感觉很多的内容严格上来说不算 Bypass)……

1x02 DLL 文件注入提权

上边说的是未使用文件的,下面来看看使用了 DLL 替换的。
第一个是监听端口的,没打算折腾这个,具体可以看这里……
第二个是转发 DLL 文件,类似于上面的方法,可以使用DLL_Hijacker.py进行更换不再赘述。

参考资料:

http://undoc.airesoft.co.uk/ntdll.dll/RtlQueryElevationFlags.php
(微软非公开 DLL )
https://en.wikipedia.org/wiki/User_Account_Control
https://www.codeproject.com/Articles/19165/Vista-UAC-The-Definitive-Guide
https://www.wilderssecurity.com/threads/malware-achieves-privilege-escalation-via-windows-uac.376464/
http://pan.baidu.com/s/1slbHD6H
https://technet.microsoft.com/en-us/library/2009.07.uac.aspx
http://paper.seebug.org/127/

posted @ 2017-03-20 20:25  _chesky  阅读(21802)  评论(0编辑  收藏  举报