保护机制
0x01 概述
操作系統提供了許多安全機制來嘗試降低或阻止緩沖區溢出攻擊帶來的安全風險,包括DEP、ASLR等。在編寫漏洞利用代碼的時候,需要特別注意目標進程是否開啟了DEP(Linux下對應NX)、ASLR(Linux下對應PIE)等機制,例如存在DEP(NX)的話就不能直接執行棧上的數據,存在ASLR的話各個系統調用的地址就是隨機化的。下面是常見的linux保護機制
0x02 canary (棧保護)
棧溢出保護是一種緩沖區溢出攻擊緩解手段,當函數存在緩沖區溢出攻擊漏洞時,攻擊者可以覆蓋棧上的返回地址來讓shellcode能夠得到執行。當啟用棧保護后,函數開始執行的時候會先往棧里插入cookie信息,當函數真正返回的時候會驗證cookie信息是否合法,如果不合法就停止程序運行。攻擊者在覆蓋返回地址的時候往往也會將cookie信息給覆蓋掉,導致棧保護檢查失敗而阻止shellcode的執行。在Linux中我們將cookie信息稱為canary。因此在編譯時可以控制是否開啟棧保護以及程度,例如:
gcc -fno-stack-protector -o test test.c //禁用棧保護 gcc -fstack-protector -o test test.c //啟用堆棧保護,不過只為局部變量中含有 char 數組的函數插入保護代碼 gcc -fstack-protector-all -o test test.c //啟用堆棧保護,為所有函數插入保護代碼0x03 fortify
這個保護機制防止緩沖區溢出攻擊。gcc生成了一些附加代碼,通過對數組大小的判斷替換strcpy, memcpy, memset等函數名,達到防止緩沖區溢出的作用。就是gcc自動對一些函數進行檢查有沒有緩沖區溢出
0x04 NX(DEP)
NX即No-eXecute(不可執行)的意思,NX(DEP)的基本原理是將數據所在內存頁標識為不可執行,當程序溢出成功轉入shellcode時,程序會嘗試在數據頁面上執行指令,此時CPU就會拋出異常,而不是去執行惡意指令。
gcc編譯器默認開啟了NX選項,如果需要關閉NX選項,可以給gcc編譯器添加-z execstack參數。例如:
在Windows下,類似的概念為DEP(數據執行保護),好像在的Visual Studio 2008以后就默認開啟了DEP編譯選項。
0x05 PIE(ASLR)
一般情況下NX(Windows平臺上稱其為DEP)和地址空間分布隨機化(ASLR)會同時工作。內存地址隨機化機制(address space layout randomization),有以下三種情況:
- 0 - 表示關閉進程地址空間隨機化。
- 1 - 表示將mmap的基址,stack和vdso頁面隨機化。
- 2 - 表示在1的基礎上增加棧(heap)的隨機化。
可以防范基于Ret2libc方式的針對DEP的攻擊。ASLR和DEP配合使用,能有效阻止攻擊者在堆棧上運行惡意代碼。
Built as PIE:位置獨立的可執行區域(position-independent executables)。這樣使得在利用緩沖溢出和移動操作系統中存在的其他內存崩潰缺陷時采用面向返回的編程(return-oriented programming)方法變得難得多。
liunx下關閉PIE的命令如下:
PIE有關的知識詳情:https://blog.csdn.net/counsellor/article/details/81543197
0x06 relro
設置符號重定向表格為只讀或在程序啟動時就解析并綁定所有動態符號,從而減少對GOT(Global Offset Table)攻擊。RELRO為” Partial RELRO”,說明我們對GOT表具有寫權限。總之,需要執行
sudo -s echo 0 > /proc/sys/kernel/randomize_va_space//可選,如果要關閉系統的ALSR功能就執行這個我們在打ctf時,可以使用下面的命令就行了
gcc -no-pie -fno-stack-protector -z execstack -m32 -o exp1 exp1.c- -op-pie:內存地址不隨機化
- -fno-stack-protector:不棧保護,沒有canary
- -z execstack :棧可執行,沒有NX
0x07 objdump
objdump命令是用查看目標文件或者可執行的目標文件的構成的gcc工具。詳情https://man.linuxde.net/objdump
-j name
–section=name 僅僅顯示指定名稱為name的section的信息
-t
–syms 顯示文件的符號表入口。類似于nm -s提供的信息
objdump -t -j .text exp1//查看read程序的.text段有哪些函數
0x08 例子
首先我們準備一個C文件
使用gcc編譯
- -m32:使用32位編譯
- -o:后面就編譯的名字
我們檢查文件的保護機制
將這些保護機制去掉:
gcc -no-pie -fno-stack-protector -z execstack -m32 -o exp1 read.c
總結
- 上一篇: 谍战之特殊较量剧情介绍
- 下一篇: 一个简单的pwn例子---read函数