1. 程式人生 > >Exp1 PC平臺逆向破解

Exp1 PC平臺逆向破解

隨機化 bof 正常 -- 執行流程 數值 1.2 位置 blog

1. 逆向及Bof基礎實踐

1.1 實踐目標

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

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

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

三個實踐內容如下
  • 手工修改可執行文件,改變程序執行流程,直接跳轉到getShell函數。
  • 利用foo函數的Bof漏洞,構造一個攻擊輸入字符串,覆蓋返回地址,觸發getShell函數。
  • 註入一個自己制作的shellcode並運行這段shellcode。

    這幾種思路,基本代表現實情況中的攻擊目標:
  • 運行原本不可訪問的代碼片段
  • 強行修改程序執行流
  • 以及註入運行任意代碼。

1.2 直接修改程序機器指令,改變程序執行流程

1.2.1 常見匯編指令

命令類指令

 MOV----> move                    傳送字或字節
 PUSH---->push                    把字壓入堆棧
 POP---->pop                      把字彈出堆棧
 

程序轉移指令 ---無條件轉移指令(長轉移)

JMP---->jump                      無條件轉移指令
CALL---->call                     過程調用
RET---->return                    過程返回
RETF---->return far               過程返回

1.2.2直接修改程序機器指令,改變程序執行流程

首先,利用objdump -d pwn1指令對pwn1進行反匯編,從圖中可以看到核心代碼。
技術分享圖片
技術分享圖片

main函數中看到程序調用了位於地址8048491處的foo函數,還可以看到存在一個getshell函數,這就是我們要跳轉的目標。

main函數調用foo對應的機器指令為e8 d7 ff ff ff。其中e8是跳轉的意思,此時此刻EIP的值是下條指令的地址:80484ba,這時CPU會執行EIP+d7ffffff指令,d7ffffff是補碼。則80484ba +d7ffffff= 0x80484ba-0x29=0x8048491,這與後面call 8048491<foo>

正好對應。
技術分享圖片
技術分享圖片

所以我們的目標是修改機器指令,讓它調用getshell,即計算0x0804847d-0x0x8048491=-3D。計算補碼為11000011=c3。之後利用vim修改機器指令。
技術分享圖片
技術分享圖片
技術分享圖片

1.2.3通過構造輸入參數,造成BOF攻擊,改變程序執行流

利用gdb確定輸入字符串哪幾個字符會覆蓋到返回地址,經過嘗試發現eip 0x35353535 0x35353535,對應數字5,再輸入確定堆棧的狀態。
技術分享圖片
技術分享圖片

這時發現eip中顯示0x34333231,則 1234 那四個數最終會覆蓋到堆棧上的返回地址,。所以只要把這四個字符替換為 getShell 的內存地址,輸給pwn2,pwn2就會運行getShell。

我們已經知道getshell內存地址為0804847d,反匯編輸入11111111222222223333333344444444\x7d\x84\x04\x08

因為沒法通過鍵盤直接輸入16進制數值,所以利用perl。

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

其中\x0a表示回車。生成input文件,之後將input作為輸入,(cat input; cat) | ./pwn2,之後就能運行指令了。
技術分享圖片

1.2.4. 註入Shellcode並執行

準備一段Shellcode。

要註意的是,堆棧內存區設置為不可執行。這樣即使是註入的shellcode到堆棧上,也執行不了。輸入命令execstack -s pwn2設置堆棧可執行。
通過execstack -q pwn2查看堆棧是否可執行。

shellcode中需要猜測返回地址的位置,需要猜測shellcode註入後的內存位置。這些都極度依賴一個事實:應用的代碼段、堆棧段每次都被OS放置到固定的內存地址。ALSR,地址隨機化就是讓OS每次都用不同的地址加載應用。這樣通過預先反匯編或調試得到的那些地址就都不正確了。使用more /proc/sys/kernel/randomize_va_space命令查看是否開啟地址隨機化。
技術分享圖片

其中

  • 0表示關閉進程地址空間隨機化。
  • 1表示將mmap的基址,stack和vdso頁面隨機化。
  • 2表示在1的基礎上增加棧(heap)的隨機化。

使用echo "0" > /proc/sys/kernel/randomize_va_space命令關閉進程地址空間隨機化。

Linux構造buf的兩種方法

  • retaddr+nop+shellcode
  • nop+shellcode+retaddr // 緩沖區足夠大

經過嘗試,只能使用retaddr+nop+shellcode構造。
使用命令perl -e ‘print "A" x 32;print "\x04\x03\x02\x01\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,構造輸入。

前面的32個A用來填滿buffer,\x04\x03\x02\x01為預留的返回地址,剩下部分為shellcode。

查看pid,並用gdb在foo函數的ret位置設置斷點,在運行窗口敲回車,回到gdb查看esp寄存器,可知地址應為0xffffd330,修改input文件預留的地址。
技術分享圖片
成功。

Exp1 PC平臺逆向破解