栈溢出笔记1.11 SafeSEH
在上節寫示例的過程中,我把要用到的POP+POP+RET指令寫在了自己的一個DLL中。POP+POP+RET指令是很常見的指令,一般函數的末尾都是這種形式,因此,系統DLL中應該是有該指令的,比如ntdll.dll中就有:?
?
圖73
我們把上節示例中的地址改成這個地址試試,沒有彈出MessageBox,說明Shellcode失效了,在調試器中看看:?
?
圖74
提示說無法處理異常,說明改了地址后的異常處理函數沒有被運行。下面我們繼續用我自己的DLL,但是重新編譯它,這次在編譯時加上“/SAFESEH”選項:?
?
圖75
再來嘗試一下(注意,重新編譯后,指令地址發生變化),還是同樣的提示。用Immunity Debugger的mona插件查看以下加載的模塊:?
?
圖76
只有exe不是SafeSEH,其它DLL都是,包括ntdll.dll。這就是本節的內容了。
為了防止基于SEH的棧溢出,Windows改進了SEH,稱為SafeSEH。從前面我們至少看到一點,啟用SafeSEH編譯的模塊,我們的Shellcode是無法利用的,系統并不會調用我們偽造的這個“異常處理函數”。
事實上,啟用SafeSEH之后,模塊中使用的異常處理函數都要提前注冊,注冊的地方就在加載配置目錄(Load Config Directory)。前面我們接觸過導出表,導入表,這個加載配置目錄也類似,屬于16中數據目錄中的一種。這樣的話,發生異常之后,調用異常處理函數前,系統會對異常處理函數地址進行檢驗,如果沒有注冊,說明這個異常處理函數有問題,就直接忽略該異常處理函數。就如我們前面所看到的,我們偽造的異常處理函數被忽略,后面的又被我們所覆蓋,因此異常無法被處理。
怎么辦呢?第一個辦法如我前面所做的,如果程序中有模塊沒有啟用SafeSEH,我們還是可以利用它來加載Shellcode。第二個辦法就是SafeSEH有個例外,就是如果異常處理函數位于已加載模塊地址范圍之外,則異常處理函數依舊會被調用。這樣機會就來了,即使程序中所有模塊都啟用了SafeSEH,或者雖然沒有啟用,但無法找到合適的指令塊做跳板。我們還可以嘗試其它不屬于該進程的模塊。
具體的做法在這篇文章中:https://www.corelan.be/index.php/2009/09/21/exploit-writing-tutorial-part-6-bypassing-stack-cookies-safeseh-hw-dep-and-aslr/。?
按他的做,很簡單,這里就不重復了。
NLS,全稱National Language Support,即本地語言支持。這個語言支持不只是文字,還有鍵盤,時間日期格式等,那么.nls后綴的文件就是相關的資源文件。這些資源文件使用的方式為內存映射,即讀取其內存空間相當于讀文件。進程結構PEB中有相應的成員:?
?
圖77
這些成員指針在進程初始化的時候指向資源文件映射之后相應的地址。
需要注意的是,雖然我們在unicode.nls找到了需要的“指令”,但unicode.nls是數據,只不過是其中的數據正好和指令操作碼相同。這與我們把Shellcode放在棧上執行時相同的。
總結
以上是生活随笔為你收集整理的栈溢出笔记1.11 SafeSEH的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 6-4-1:STL之list——list
- 下一篇: 【转】如何设计动态(不定)字段的产品数据