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項目
項目總結了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
的地方:
雙擊跳轉到變量定義位置,就可以找到虛函數表!
如何調用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