Exp1 PC平臺逆向破解
實踐目標
本次實踐的對象是一個名為pwn1的linux可執行文件。該程序正常執行流程是:main調用foo函數,foo函數會簡單回顯任何用戶輸入的字符串。該程序同時包含另一個代碼片段,getShell,會返回一個可用Shell。正常情況下這個代碼是不會被運行的。我們實踐的目標就是想辦法運行這個代碼片段。我們將學習兩種方法運行這個代碼片段,然后學習如何注入運行任何Shellcode。
三個實踐內容如下:
- 1.手工修改可執行文件,改變程序執行流程,直接跳轉到getShell函數。
- 2.利用foo函數的Bof漏洞,構造一個攻擊輸入字符串,覆蓋返回地址,觸發getShell函數。
- 3.注入一個自己制作的shellcode并運行這段shellcode。
這幾種思路,基本代表現實情況中的攻擊目標:
- 運行原本不可訪問的代碼片段
- 強行修改程序執行流
- 以及注入運行任意代碼
基礎知識
- 熟悉Linux基本操作,能看懂常用指令,如管道(|),輸入、輸出重定向(>)等。
- 理解Bof的原理。
- 能看得懂匯編、機器指令、EIP、指令地址。
- NOP:NOP指令即“空指令”。執行到NOP指令時,CPU什么也不做,僅僅當做一個指令執行過去并繼續執行NOP后面的一條指令。
- JNE:條件轉移指令,如果不相等則跳轉。
- JE:條件轉移指令,如果相等則跳轉。
- JMP:無條件轉移指令。
- CMP:比較指令,功能相當于減法指令,只是對操作數之間運算比較,不保存結果。cmp指令執行后,將對標志寄存器產生影響。其他相關指令通過識別這些被影響的標志寄存器位來得知比較結果。
- 會使用gdb,vi。
1直接修改程序機器指令,改變程序執行流程
-
知識要求:Call指令,EIP寄存器,指令跳轉的偏移計算,補碼,反匯編指令objdump,十六進制編輯工具
-
學習目標:理解可執行文件與機器指令
-
進階:掌握ELF文件格式,掌握動態技術
--
1.1反匯編pwn1文件
輸入命令:objdump -d 文件名 | more
下面只保留了最核心的幾行代碼


"call 8048491 "是匯編指令,是說這條指令將調用位于地址8048491處的foo函數;其對應機器指令為“e8 d7ffffff”,e8即跳轉之意。
本來正常流程,此時此刻EIP的值應該是下條指令的地址,即80484ba,但如一解釋e8這條指令,CPU就會轉而執行 “EIP + d7ffffff”這個位置的指令。“d7ffffff”是補碼,表示-41,41=0x29,80484ba +d7ffffff= 80484ba-0x29正好是8048491這個值。
main函數調用foo,對應機器指令為“e8 d7ffffff”,
那我們想讓它調用getShell,只要修改“d7ffffff”為,"getShell-80484ba"對應的補碼就行。
用Windows計算器,直接 47d-4ba就能得到補碼,是c3ffffff。
下面我們就修改可執行文件,將其中的call指令的目標地址由d7ffffff變為c3ffffff。
1.2修改可執行文件,將其中的call指令的目標地址由d7ffffff變為c3ffffff
對pwn1進行備份,將對備份文件hyt進行操作。
root@KaliYL:~# cp pwn1 hyt (我的pwn1在桌面上,我直接在桌面上copy了)
root@KaliYL:~# vi pwn2
使用命令:vi hyt 在vim編輯器查看可執行文件hyt
在編輯器內按ESC鍵,輸入命令:%!xxd將顯示模式切換為16進制模式,如下圖:

查找要修改的內容
輸入命令:/e8 d7,如下圖:

在vim的普通模式下,按r鍵修改d7為c3。如圖:

輸入命令:%!xxd -r ,轉換16進制為原格式
輸入命令:wq , 存盤退出vi
反匯編看一下,call指令是否正確調用getShell

運行下改后的代碼,會得到shell提示符#

2通過構造輸入參數,造成BOF攻擊,改變程序執行流
2.1基本原理
我們的目標是觸發getShell函數,該可執行文件正常運行是調用函數foo,這個函數有Buffer overflow漏洞,讀入字符串時系統只預留了__字節的緩沖區,超出部分會造成溢出,我們的目標是覆蓋返回地址。
2.2確認輸入字符串哪幾個字符會覆蓋到返回地址
使用GDB調試工具調試,確認用什么值來覆蓋返回地址gdb pwn1進入調試,并輸入一串可讓其溢出的字符:

輸入命令:info r eip,
查看溢出時寄存器狀態如下:

查看指令寄存器eip內的值為0x34333231,通過對照ASCII碼表,可知對應的值為4321,即覆蓋了返回地址的值,需要對它進行修改,只要把這四個字符替換為 getShell 的內存地址,輸給pwn1,pwn1就會運行getShell。
2.3 確認用什么值來覆蓋返回地址
getShell的內存地址,通過反匯編時可以看到,即0804847d。對比之前 eip 0x34333231 0x34333231,正確應用輸入 11111111222222223333333344444444\x7d\x84\x04\x08
2.4構造輸入字符串
由為我們沒法通過鍵盤輸入\x7d\x84\x04\x08這樣的16進制值,所以先生成包括這樣字符串的一個文件。\x0a表示回車,如果沒有的話,在程序運行時就需要手工按一下回車鍵。再通過xxd查看文件十六進制格式的內容。

然后將input的輸入,通過管道符“|”,作為4322的輸入。

3注入Shellcode并執行
3.1準備一段Shellcode
- shellcode就是一段機器指令(code)
- 通常這段機器指令的目的是為獲取一個交互式的shell(像linux的shell或類似windows下的cmd.exe),所以這段機器指令被稱為shellcode。
- 在實際的應用中,凡是用來注入的機器指令段都通稱為shellcode,像添加一個用戶、運行一條指令。
3.2準備工作
設置堆棧可執行命令:execstack -s 4322
查詢文件的堆棧是否可執行命令:execstack -q 4322
查看地址是否隨機化命令:more /proc/sys/kernel/randomize_va_space 0為關閉,2為打開
關閉地址隨機化命令:echo "0" > /proc/sys/kernel/randomize_va_space

3.3構造要注入的shellcode
- Linux下有兩種基本構造攻擊buf的方法:
- retaddr+nop+shellcode
- nop+shellcode+retaddr
- 本次實驗采用了retaddr+nop+shellcode的方法
將寫好的代碼通過管道方式輸入給程序4322中的foo函數進行覆蓋 (cat input_shellcode;cat) | ./4322
輸入完指令只需要按一次回車,然后我們需要打開另一個終端.

3.4打開另外一個終端
用gdb來調試這個進程
首先找到4322程序的進程號ps -ef | grep 4322
啟動gdb調試這個程序 gdb attach 624

通過disassemble foo 命令進行反匯編,并設置斷點,來查看注入buf的內存地址
輸入c使其繼續運行,同時在原來的終端里回車,再返回調試終端。

3.4修改注入代碼的覆蓋地址
使用info r esp命令查找地址,再用x/16x 命令加查找出的地址來查看其存放內容。
可以知道 01010304 所在的地址為 0xffffd36c,那么注入的shellcode代碼的地址應該在該地址后四個字節的位置,即0xffffd36c + 0x00000004 = 0xffffd370(老師,因為之前做錯了好幾次,之后做的時候發現這里忘記截圖了)
修改注入代碼的覆蓋地址如圖

攻擊成功!
實踐感想
通過本次實驗,我對網絡攻擊有了更加深入的了解,在實驗過程中出現了很多問題,在同學的幫助以及回憶老師上課講的知識點,掌握了如何手工修改可執行文件,改變程序執行流程,直接跳轉到getShell函數。
學會了如何利用foo函數的Bof漏洞,構造一個攻擊輸入字符串,覆蓋返回地址,觸發getShell函數。練習了怎么去注入一個自己制作的shellcode并運行這段shellcod,也大概明白了其中的原理,同時也對linux操作
系統越來越熟悉,完成這個實驗也給了我挺大的成就感,讓我變得更加細心、耐心。
什么是漏洞?有什么危害
根據自己的理解漏洞一個就是一些程序員沒有想到的邊界問題,被網絡攻擊者利用,對網絡進行攻擊。
在這個數字化時代網絡漏洞可能會造成信息泄露、網絡癱瘓、錢財損失。
浙公網安備 33010602011771號