[Windows] 用 setdllcharacteristics 將 PE 檔案強制開啟 DEP/ASLR 旗標
最近公司在推行 Windows 專案都要開啟 DEP/ASLR,增強我們產品本身的安全性~
當然我們自己寫的程式沒什麼問題,
Visual Studio 2015 編譯出來的 .exe 和 .dll 預設就會將 DEP/ASLR 打開,
可是我們有用到一些 3rd-party 的工具,像是 7-zip,
甚或是微軟本身一些舊的 DLL (像 MSVCR71.dll),它們都沒有開 DEP/ASLR,要怎麼辦呢?
跟公司的 IT 部門有些爭論,不過他們還蠻堅持所有產品出的 PE 檔案,
都得開 DEP/ASLR,不管是自己寫的,還是 3rd-party 的…
幸好後來找到了一個工具 setdllcharacteristics,可以在「編譯之後」,才將 DEP/ASLR 的旗標打開~
setdllcharacteristics 是一個用 C 寫的程式,在各種平台上 (Windows/Linux/Mac) 上都可以編譯使用,
它做的事情很簡單:找出 PE 檔案標頭中關於 DEP/ASLR 旗標的位置,然後調整它的值。
老實說我也是看到了它的說明,才知道原來程式的 DEP/ASLR 只是設定 PE header 的一個欄位,
然後 Windows 在載入程式時,就會根據這欄位的值,決定是否要開啟 DEP/ASLR 的功能~
但在用這個工具的時候要注意的是,如果 PE 檔案本身是有數位簽章 (digital signature) 的話,
修改 PE header 是會讓簽章失效的,因此比較建議是在沒有簽章的檔案上使用~
來看一下要怎麼使用 setdllcharacteristics 吧~
1. 先確認 PE 檔案目前的 DEP/ASLR 狀態
我們可以用 pev 工具來檢查 Windows PE 檔案是否有開啟 DEP/ASLR,
這邊以微軟的 MSVCR71.dll 來當例子,可以看到 DEP/ASLR 的旗標都是關閉的:
testuser@localhost ~ $ pesec MSVCR71.dll ASLR: no DEP/NX: no SEH: yes Stack cookies (EXPERIMENTAL): yes
2. 使用 setdllcharacteristics 修改 DEP/ASLR 旗標
在 setdllcharacteristics 網頁上可以找到它的原始碼,目前是 setdllcharacteristics_v0_0_0_1.zip,
解開之後裡面就有個 setdllcharacteristics.exe 可以在 Windows 上用,
不過我平常的工作環境是 Mac,因此需要自己編譯它附帶的 setdllcharacteristics.c~
用 gcc 就可以很容易編譯了:
gcc setdllcharacteristics.c -o setdllcharacteristics
直接執行編譯出來的 setdllcharacteristics 看一下用法:
testuser@localhost ~ $ ./setdllcharacteristics Usage: setdllcharacteristics [options] file setdllcharacteristics V0.0.0.1, set PE-file DLLCHARACTERISTICS like DYNAMIC_BASE (ASLR), NX_COMPAT (DEP) and FORCE_INTEGRITY (check signature). options: +d set DYNAMIC_BASE flag (ASLR) -d clear DYNAMIC_BASE flag (ASLR) +n set NX_COMPAT flag (DEP) -n clear NX_COMPAT flag (DEP) +f set FORCE_INTEGRITY flag (check signature) -f clear FORCE_INTEGRITY flag (check signature) Source code put in the public domain by Didier Stevens, no Copyright Use at your own risk http://didierstevens.com
像我們想要打開 MSVCR71.dll 的 DEP/ASLR 旗標,就使用 +d +n 這兩個參數:
testuser@localhost ~ $ ./setdllcharacteristics +d +n MSVCR71.dll Original DLLCHARACTERISTICS = 0x0000 DYNAMIC_BASE = 0 NX_COMPAT = 0 FORCE_INTEGRITY = 0 Updated DLLCHARACTERISTICS = 0x0140 DYNAMIC_BASE = 1 NX_COMPAT = 1 FORCE_INTEGRITY = 0
3. 再次確認 PE 檔案目前的 DEP/ASLR 狀態
再用 pesec 看一次 MSVCR71.dll 的 DEP/ASLR 狀態,果真旗標都已經被打開了:
testuser@localhost ~ $ pesec MSVCR71.dll ASLR: yes DEP/NX: yes SEH: yes Stack cookies (EXPERIMENTAL): yes
用檔案比較軟體 Beyond Compare 來看一下修改後的 PE 檔,
可以注意到左邊 (修改前) 的 PE header,從原本的 00 00 被改成了 40 01,
開啟 DEP/ASLR 就只是將這兩個 byte 做一下更動而已:
如果是自己寫的程式,建議還是在編譯器中打開 DEP/ASLR 的選項 (VS2015 預設開啟),
遇到 3rd-party 工具,就可以考慮使用強制修改旗標的方式囉~
參考資料:Flawed 7-Zip compression tool opens systems to hack. Update it now!