官术网_书友最值得收藏!

2.6.10 W^X

多種操作系統,包括OpenBSD、Windows、Linux和OS X,在內核強制減少權限,使得進程地址空間中的任何部分都不能同時既可寫又可執行。這一策略被稱為W xor X,或更為簡潔的W ^ X,并通過使用多種CPU的不執行(No eXecute,NX)位來支持這種功能。

NX位使內存頁可以標記為數據,以禁用這些頁面上的代碼的執行。該位在AMD的CPU上名為NX,在Intel CPU上名為XD(eXecute Disable,執行禁用),而在ARM版本6和更高版本的CPU上名為XN(eXecute Never,從不執行)。大部分最新的英特爾CPU和目前所有的AMD CPU都支持此功能。

W^X要求,不是程序本身的一部分的任何代碼,都不可以執行。這可以防止執行棧、堆或數據段上的shellcode。W^X還可以防止故意在數據頁執行代碼。例如,一個即時(Just-In-Time,JIT)編譯器通常從外部數據(如字節碼)構造匯編代碼,然后執行它。要在這樣的環境中工作,JIT編譯器必須符合這些限制,例如,確保包含可執行指令的頁面被適當地標記。

數據執行保護。數據執行保護(Data Execution Prevention,DEP)是W^X策略在微軟Visual Studio中的實現。DEP使用NX技術,以防止存儲在數據段中的指令的執行。這個功能自XP Service Pack2以來一直在Windows中可用。DEP假設:不是程序本身的一部分的任何代碼都不可執行。因此,它不妥善地處理在“禁止”頁面中試圖執行的代碼。例如,JIT編譯器通常從外部數據(如字節碼)構造匯編代碼,然后執行它,這種操作只能被DEP阻止。此外,DEP經常可以揭露隱藏在軟件中的錯誤。

如果你的應用程序是針對Windows XP Service Pack3開發的,那么你應該調用SetProcessDEPPolicy()來強制執行DEP/NX。如果不清楚應用程序是否將運行在一個低級別的平臺,包括對SetProcessDEPPolicy()的支持,請盡早在啟動代碼中調用以下代碼。


01  BOOL __cdecl EnableNX(void) {
02     HMODULE hK = GetModuleHandleW(L"KERNEL32.DLL");
03     BOOL (WINAPI *pfnSetDEP)(DWORD);
04  
05     *(FARPROC *) &pfnSetDEP = 
06       GetProcAddress(hK, "SetProcessDEPPolicy");
07     if (pfnSetDEP) 
08        return (*pfnSetDEP)(PROCESS_DEP_ENABLE);
09     return(FALSE);
10  }

如果你的應用程序包含自修改代碼或執行JIT編譯,那么DEP可能導致應用程序失敗。為了緩解這個問題,你還是應該選擇DEP(見下面的鏈接器開關)并把將用于JIT編譯的任何數據標記如下。


01  PVOID pBuff = VirtualAlloc(NULL,4096,MEM_COMMIT,PAGE_READWRITE);
02  if (pBuff) {
03    // 
復制可執行的匯編(ASM
)代碼至緩沖區
04    memcpy_s(pBuff, 4096);
05   
06    // 
緩沖區已就緒,因此把它標記為可執行并執行寫保護
07    DWORD dwOldProtect = 0;
08    if (!VirtualProtect(pBuff,4096,PAGE_EXECUTE_READ,&dwOldProtect)
09       ) {
10      // 
出錯
11    } else {
12      // 
調用pBuff
13    }
14    VirtualFree(pBuff,0,MEM_RELEASE);
15  }

DEP / NX對Windows的性能沒有影響。要啟用DEP,你應該把你的代碼用/NXCOMPAT鏈接或調用SetProcessDEPPolicy()并在具有DEP功能的CPU上測試你的應用程序,然后記錄并修復任何因使用DEP而導致的故障。在Vista或更高版本的Windows中,使用/NXCOMPAT類似于調用SetProcessDEPPolicy()。不過,Windows XP的裝載器不能識別/NXCOMPAT鏈接選項。因此,使用SetProcessDEPPolicy()一般是首選的。

ASLR和DEP在Windows平臺上提供不同的保護。因此,你應該對所有的二進制文件同時啟用(/DYNAMICBASE和/NXCOMPAT)兩種機制。

主站蜘蛛池模板: 缙云县| 禹州市| 沈阳市| 西林县| 阳朔县| 如东县| 北宁市| 开封市| 六枝特区| 麦盖提县| 惠州市| 石首市| 沽源县| 曲麻莱县| 玉树县| 临夏市| 桂阳县| 堆龙德庆县| 仁怀市| 浮山县| 成安县| 南开区| 吴旗县| 淮南市| 鹤山市| 兴山县| 姚安县| 鄂尔多斯市| 漳平市| 曲阳县| 彰化县| 通江县| 房产| 敦化市| 兴海县| 望江县| 渑池县| 岳池县| 米泉市| 河源市| 辉南县|