首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> VC 教學

Windows NT/2000 下無需驅動程式即可執行 Ring 0 代碼的實現方法

     編輯:VC 教學

Windows NT/2000 為了確保系統可靠性,嚴格劃分了核心模式與使用者模式,在 x86 架構上分別對應 CPU 的 Ring 0 與 Ring 3 權限等級。Ring 0 允許執行特權指令、存取任意 I/O 裝置等。若要從使用者態(Ring 3)進入核心態(Ring 0),必須透過 CPU 的門機制,如中斷門、呼叫門等。Windows NT/2000 提供的系統服務(int 2eh 中斷)僅允許呼叫系統預定義的服務,若想執行自訂的 Ring 0 代碼,傳統做法是編寫裝置驅動程式。本文介紹一種在使用者態下、不依賴任何驅動程式即可執行 Ring 0 代碼的技術。

核心原理:構造自訂呼叫門

Windows NT/2000 將裝置驅動程式載入核心位址空間(通常位於 0x80000000 以上),由 DPL 為 0 的 GDT 項目 8(CS=8)實現 Ring 0 權限。本文的思路是在系統中建立一個指向我們代碼的呼叫門,藉此實現 Ring 0 代碼執行。關鍵在於構造屬於自己的 Call Gate。Call Gate 由全域描述符表(GDT)定義,GDT 基址可透過 sgdt 指令取得(非特權指令,Ring 3 可執行)。GDT 位於核心區域,一般使用者程式無法直接存取該記憶體區域。

突破記憶體存取限制:PhysicalMemory 區段物件

幸運的是,Windows NT/2000 提供了一個名為 PhysicalMemory 的區段核心物件,位於 \Device 路徑下。透過這個物件可以操作實體記憶體。使用 objdir.exe 分析其 DACL 可見,預設僅 SYSTEM 帳號擁有讀寫權限,Administrators 僅有讀取權限,一般使用者則無權限。但若擁有 Administrator 權限,即可透過 GetSecurityInfo、SetEntriesInAcl、SetSecurityInfo 等 API 修改該物件的 ACE,賦予當前使用者寫入權限。這就是示例代碼需要 Administrator 權限的原因。

關鍵代碼實現

以下函數示範如何為 PhysicalMemory 區段物件新增可寫入的 ACE:

VOID SetPhyscialMemorySectionCanBeWrited(HANDLE hSection)
{
    PACL pDacl = NULL;
    PACL pNewDacl = NULL;
    PSECURITY_DESCRIPTOR pSD = NULL;
    DWORD dwRes;
    EXPLICIT_ACCESS ea;

    if ((dwRes = GetSecurityInfo(hSection, SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION,
        NULL, NULL, &pDacl, NULL, &pSD)) != ERROR_SUCCESS)
    {
        printf("GetSecurityInfo Error %u\n", dwRes);
        goto CleanUp;
    }

    ZeroMemory(&ea, sizeof(EXPLICIT_ACCESS));
    ea.grfAccessPermissions = SECTION_MAP_WRITE;
    ea.grfAccessMode = GRANT_ACCESS;
    ea.grfInheritance = NO_INHERITANCE;
    ea.Trustee.TrusteeForm = TRUSTEE_IS_NAME;
    ea.Trustee.TrusteeType = TRUSTEE_IS_USER;
    ea.Trustee.ptstrName = "CURRENT_USER";

    if ((dwRes = SetEntriesInAcl(1, &ea, pDacl, &pNewDacl)) != ERROR_SUCCESS)
    {
        printf("SetEntriesInAcl %u\n", dwRes);
        goto CleanUp;
    }

    if ((dwRes = SetSecurityInfo(hSection, SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION,
        NULL, NULL, pNewDacl, NULL)) != ERROR_SUCCESS)
    {
        printf("SetSecurityInfo %u\n", dwRes);
        goto CleanUp;
    }

CleanUp:
    if (pSD) LocalFree(pSD);
    if (pNewDacl) LocalFree(pNewDacl);
}

執行後,PhysicalMemory 物件將新增一條 ACE,授予當前使用者 SECTION_MAP_WRITE 權限,從而允許修改 GDT、植入呼叫門,最終實現無驅動執行 Ring 0 代碼。

安全性與風險提示

此技術雖展示了核心機制的可控性,但修改核心記憶體結構極度危險,稍有不慎即導致系統崩潰。實際開發中應優先考慮正規驅動開發模型,僅在極特殊的研究或除錯場景下參考此法。現代 Windows 版本(含 Patch Guard、HVCI 等防護機制)已大幅限制此類操作,本文僅供歷史技術參考。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved