DEP原理及關閉

一、原理

  DEP - 數據執行保護的縮寫,Data Execution Prevention。 他是一套軟硬件技術,能夠在內存上執行額外檢查以幫助防止在系統上運行惡意代碼。其基本原理是將數據所在內存頁標識爲不可執行,當程序溢出成功轉入shellcode時,程序會嘗試在數據頁面上執行指令,此時CPU就會拋出異常,而不是去執行惡意指令。如圖所示

 

        DEP 的主要作用是阻止數據頁(如默認的堆頁、各種堆棧頁以及內存池頁)執行代碼。微軟從Windows XP SP2開始提供這種技術支持,根據實現的機制不同可分爲:軟件DEP(Software DEP)和硬件DEP(Hardware-enforced DEP)。

二、分類 

       軟件DEP其實就是SafeSEH,它的目的是阻止利用S.E.H的攻擊,這種機制與CPU硬件無關,Windows利用軟件模擬實現DEP,對操作系統提供一定的保護。SafeSEH會在校驗過程中去檢查異常處理函數是否位於非可執行頁上。

  硬件DEP纔是真正意義的DEP,硬件DEP需要CPU的支持,AMD和Intel都爲此做了設計,AMD稱之爲No-Execute Page-Protection (NX),Intel稱之爲Execute Disable Bit (XD) ,兩者功能及工作原理在本質上是相同的。

  操作系統通過設置內存頁的NX/XD屬性標記,來指明不能從該內存執行代碼。爲了實現這個功能,需要在內存的頁面表(Page Table)中加入一個特殊的標識位(NX/XD)來標識是否允許在該頁上執行指令。當該標識位設置爲0裏表示這個頁面允許執行指令,設置爲1時表示該頁面不允許執行指令。

  這裏只對硬件DEP進行討論和分析。

     大家可以通過如下方法檢查CPU是否支持硬件DEP,右鍵單擊桌面上的"我的電腦"圖標,選擇"屬性",在打開的"系統屬性"窗口中點擊"高級"選項卡。在"高級"選項卡頁面中的"性能"下單擊"設置"打開"性能選項"頁。單擊"數據執行保護"選項卡,在該頁面中我們可確認自己計算機的CPU是否支持DEP。如果CPU不支持硬件DEP該頁面底部會有如下類似提示:"您的計算機的處理器不支持基於硬件的DEP。但是,Windows可以使用DEP軟件幫助保護免受某些類型的攻擊"。如圖所示。

  


 

  根據啓動參數的不同,DEP工作狀態可以分爲四種。

  (1)Optin:默認僅將DEP保護應用於Windows系統組件和服務,對於其他程序不予保護,但用戶可以通過應用程序兼容性工具(ACT,Application Compatibility Toolkit)爲選定的程序啓用DEP,在Vista下邊經過/NXcompat選項編譯過的程序將自動應用DEP。這種模式可以被應用程序動態關閉,它多用於普通用戶版的操作系統,如Windows XP、Windows Vista、Windows7。

  (2)Optout:爲排除列表程序外的所有程序和服務啓用DEP,用戶可以手動在排除列表中指定不啓用DEP保護的程序和服務。這種模式可以被應用程序動態關閉,它多用於服務器版的操作系統,如 Windows 2003、Windows 2008。

  (3)AlwaysOn:對所有進程啓用DEP 的保護,不存在排序列表,在這種模式下,DEP不可以被關閉,目前只有在64位的操作系統上才工作在AlwaysOn模式。

  (4)AlwaysOff:對所有進程都禁用DEP,這種模式下,DEP也不能被動態開啓,這種模式一般只有在某種特定場合才使用,如DEP干擾到程序的正常運行。

  我們可以通過切換上圖中的複選框切換Optin和Optout兩種模式。還可以通過修改c:boot.ini中的/noexecute啓動項的值來控制DEP的工作模式。如圖所示,DEP在該操作系統上的工作模式爲Optout。

  


 

三、VS環境設置

  介紹完DEP的工作原理及狀態後,我們來看一個和DEP密切相關的程序鏈接選項:/NXCOMPAT。/NXCOMPAT是Visual Studio 2005及後續版本中引入一個鏈接選項,默認情況下是開啓的。在本書中使用的Visual Studio 2008 (VS 9.0)中,可以在通過菜單中的Project→project Properties→Configuration Properties→Linker→Advanced→Data Execution Prevention (DEP)中選擇是不是使用/NXCOMPAT編譯程序,如圖所示。

  


 

  採用/NXCOMPAT編譯的程序會在文件的PE頭中設置IMAGE_DLLCHARACTERISTICS_ NX_COMPAT標識,該標識通過結構體IMAGE_OPTIONAL_HEADER中的DllCharacteristics變量進行體現,當DllCharacteristics設置爲0x0100表示該程序採用了/NXCOMPAT編譯。關於結構體IMAGE_OPTIONAL_HEADER的詳細說明大家可以查閱MSDN相關資料,在這我們就不過多討論了。

  經過/NXCOMPAT編譯的程序有什麼好處呢?通過前面的介紹我們知道用戶版的操作系統中DEP一般工作在Optin狀態,此時DEP只保護系統核心進程,而對於普通的程序是沒有保護的。雖然用戶可以通過工具自行添加,但這無形中增高了安全的門檻,所以微軟推出了/NXCOMPAT編譯選項。經過/NXCOMPAT編譯的程序在Windows vista及後續版本的操作系統上會自動啓用DEP保護。

四、分析

  DEP針對溢出攻擊的本源,完善了內存管理機制。通過將內存頁設置爲不可執行狀態,來阻止堆棧中shellcode的執行,這種釜底抽薪的機制給緩衝溢出帶來了前所未有的挑戰。這也是迄今爲止在本書中我們遇到的最有力的保護機制,它能夠徹底阻止緩衝區溢出攻擊麼?答案是否定的。

  如同前面介紹的安全機制一樣,DEP也有着自身的侷限性。

  首先,硬件DEP需要CPU的支持,但並不是所有的CPU都提供了硬件DEP的支持,在一些比較老的CPU上邊DEP是無法發揮作用的。

  其次,由於兼容性的原因Windows不能對所有進程開啓DEP保護,否則可能會出現異常。例如一些第三方的插件DLL,由於無法確認其是否支持DEP,對涉及這些DLL的程序不敢貿然開啓DEP保護。再有就是使用ATL 7.1或者以前版本的程序需要在數據頁面上產生可以執行代碼,這種情況就不能開啓DEP保護,否則程序會出現異常。

  再次,/NXCOMPAT編譯選項,或者是IMAGE_DLLCHARACTERISTICS_NX_COMPAT的設置,只對Windows Vista 以上的系統有效。在以前的系統上,如Windows XP SP3等,這個設置會被忽略。也就是說,即使採用了該鏈接選項的程序在一些操作系統上也不會自動啓用DEP保護。

  最後,當DEP工作在最主要的兩種狀態Optin和Optout下時,DEP是可以被動態關閉和開啓的,這就說明操作系統提供了某些API函數來控制DEP的狀態。同樣很不幸的是早期的操作系統中對這些API函數的調用沒有任何限制,所有的進程都可以調用這些API函數,這就埋下了很大的安全隱患,也爲我們突破DEP提供了一條道路。

五、突破DEP的C代碼

#include 〈windows.h〉

typedef enum _PROCESSINFOCLASS
{
        ProcessDebugPort=0x22
} PROCESSINFOCLASS;

#define  MEM_EXECUTE_OPTION_ENABLE 0x2

typedef DWORD
(CALLBACK * NTSETINFORMATIONPROCESS)(
                                    
                                     IN HANDLE               ProcessHandle,
                                     IN PROCESSINFOCLASS     ProcessInformationClass,
                                     IN PVOID                   ProcessInformation,
                                     IN ULONG                 ProcessInformationLength );


NTSETINFORMATIONPROCESS NtSetInformationProcess;


BOOL CloseProcessDEP()
{
    HMODULE hNtdll;
    hNtdll = LoadLibraryA("ntdll.dll");
    if(hNtdll == NULL)
    {
        OutputDebugStringA("LoadLibraryA ntdll.dll Error\n");
        return 0;
    }
    NtSetInformationProcess = (NTSETINFORMATIONPROCESS)GetProcAddress(hNtdll, "NtSetInformationProcess");

    if(NtSetInformationProcess==NULL)
    {
        OutputDebugStringA("GetProcAddress NtSetInformationProcess Error\n");
        return 0;
    }


    ULONG ExecuteFlags = MEM_EXECUTE_OPTION_ENABLE;

    //這裏調用關閉DEP
    DWORD dwRet=NtSetInformationProcess(GetCurrentProcess(),ProcessDebugPort, &ExecuteFlags,sizeof(ExecuteFlags));

    if(dwRet != 0)
    {
        OutputDebugStringA("NtSetInformationProcess Error\n");
        return 0;
    }
    return 1;
}

 
繞過dep的理論基礎是建立在這樣一個函數上的。

  ULONG ExecuteFlags = MEM_EXECUTE_OPTION_ENABLE;
 
    NtSetInformationProcess(
    NtCurrentProcess(), // (HANDLE)-1
    ProcessExecuteFlags, // 0x22
    &ExecuteFlags, // ptr to 0x2
    sizeof(ExecuteFlags)); // 0x4
    
        當MEM_EXECUTE_OPTION_ENABLE 設置爲 0x2時,則表示禁用NX(Non-Executable) Support. 其中第一個參數可以設置爲當前進程。
     
        MS的設計原因,導致改函數可以在用戶態調用,也就是說在用戶態,可以通過調用該函數,來禁用當前進程的NX支持,從而繞過dep。那麼調用了一次該函數後,該線程或進程的堆棧空間就是沒有DEP保護的了,就可以用來執行shellcode了!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章