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.dll
的 string
,可以直接在这个网站看,用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
可以知道这个dll
和uac
直接相关了。
下面在 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 Bypass 有很多种方法,目前获得 CVE 编号的仅有CVE-2010-4398
,是利用栈溢出的。(似乎看到说 UAC 是选择是用户的责任,因此微软不怎么承认 UAC 绕过……
目前公开的方法中,有以下几种方法绕过 UAC:
1,白名单提权机制;如Wusa.exe Bypass UAC
,infDefault.exe Bypass UAC
,PkgMgr.exe Bypass UAC
等。
2,DLL 劫持;
3,Windows 自身漏洞提权;
4,远程注入;
5,COM 接口技术。
其余的如通过计划任务、路径欺骗等方式不算入绕过,因为这是经过用户同意的。绕过应当是对于一位对计算机较为了解的用户(了解文件路径、能看懂UAC提示信息)在完全不知情的情况下进行的。
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
进行更换不再赘述。
1x03 0day
()
参考资料:
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/